File Coverage

blib/lib/Net/DHCP/Config/Utilities/Options.pm
Criterion Covered Total %
statement 69 85 81.1
branch 31 48 64.5
condition 2 3 66.6
subroutine 12 12 100.0
pod 7 8 87.5
total 121 156 77.5


line stmt bran cond sub pod time code
1             package Net::DHCP::Config::Utilities::Options;
2              
3 7     7   112799 use 5.006;
  7         40  
4 7     7   34 use strict;
  7         10  
  7         117  
5 7     7   26 use warnings;
  7         14  
  7         164  
6 7     7   936 use Net::CIDR;
  7         9689  
  7         6389  
7              
8             =head1 NAME
9              
10             Net::DHCP::Config::Utilities::Options - Helper utilities for working with DHCP options.
11              
12             =head1 VERSION
13              
14             Version 0.0.1
15              
16             =cut
17              
18             our $VERSION = '0.0.1';
19              
20              
21             =head1 SYNOPSIS
22              
23             use Net::DHCP::Config::Utilities::Options;
24            
25             my $dhcp_options=Net::DHCP::Config::Utilities::Options->new;
26            
27             my $options=$dhcp_options->get_options;
28             use Data::Dumper;
29             print Dumper( $options );
30              
31             my $error=$dhcp_options->validate_option( 'dns', '192.168.0.1 , 10.10.10.10' );
32             if ( defined( $error ) ){
33             die( $error );
34             }
35              
36             =head1 METHODS
37              
38             =head2 new
39              
40             Initiates the object.
41              
42             my $dhcp_options=Net::DHCP::Config::Utilities::Options->new;
43              
44             =cut
45              
46             sub new {
47 12     12 1 435 my $self={
48             options=>{
49             'mask'=>{
50             'code'=>'0',
51             'multiple'=>'0',
52             'type'=>'ip',
53             'long'=>'subnet-mask',
54             },
55             'time-offset'=>{
56             'code'=>'1',
57             'multiple'=>'0',
58             'type'=>'int',
59             'long'=>'time-offset',
60             },
61             'routers'=>{
62             'code'=>'3',
63             'multiple'=>'1',
64             'type'=>'ip',
65             'long'=>'routers',
66             },
67             'ntp'=>{
68             'code'=>'4',
69             'multiple'=>'1',
70             'type'=>'ip',
71             'long'=>'time-servers',
72             },
73             'dns'=>{
74             'code'=>'6',
75             'multiple'=>'1',
76             'type'=>'ip',
77             'long'=>'domain-name-servers',
78             },
79             'root'=>{
80             'code'=>'17',
81             'multiple'=>'0',
82             'type'=>'txt',
83             'long'=>'root-path',
84             },
85             'mtu'=>{
86             'code'=>'26',
87             'multiple'=>'0',
88             'type'=>'int',
89             'long'=>'interface-mtu',
90             },
91             'broadcast'=>{
92             'code'=>'28',
93             'multiple'=>'0',
94             'type'=>'ip',
95             'long'=>'broadcast-address',
96             },
97             'lease-time'=>{
98             'code'=>'51',
99             'multiple'=>'0',
100             'type'=>'int',
101             'long'=>'dhcp-lease-time',
102             },
103             'tftp-server'=>{
104             'code'=>'66',
105             'multiple'=>'0',
106             'type'=>'txt',
107             'long'=>'next-server',
108             },
109             'bootfile'=>{
110             'code'=>'67',
111             'multiple'=>'0',
112             'type'=>'txt',
113             'long'=>'filename',
114             },
115             'v4-access-domain'=>{
116             'code'=>'213',
117             'multiple'=>'0',
118             'type'=>'txt',
119             'long'=>'v4-access-domain',
120             },
121             'web-proxy'=>{
122             'code'=>'252',
123             'multiple'=>'0',
124             'type'=>'txt',
125             'long'=>'web-rpoxy',
126             },
127             },
128             long_to_short=>{
129             'filename'=>'bootfile',
130             'next-server'=>'tftp-server',
131             'dhcp-lease-time'=>'lease-time',
132             'interface-mtr'=>'mtu',
133             'root-path'=>'root',
134             'domain-name-servers'=>'dns',
135             'time-servers'=>'ntp',
136             'broadcast-address'=>'broadcast',
137             'subnet-mask'=>'mask',
138             },
139             };
140 12         27 bless $self;
141              
142 12         30 return $self;
143             }
144              
145             =head2 get_code
146              
147             Returns the DHCP code value for a option.
148              
149             One option is taken and that is the option name.
150              
151             If the option name is not found or is undef,
152             then undef is returned.
153              
154             # you can use the long name
155             print 'subnet-mask: '.$dhcp_options->get_code('subnet-mask')."\n";
156             # or the easier to remember short name
157             print 'mask: '.$dhcp_options->get_code('mask')."\n";
158              
159             =cut
160              
161             sub get_code{
162 1     1 1 267 my $self=$_[0];
163 1         2 my $option=$_[1];
164              
165             # need a value to proceed
166 1 50       5 if ( !defined( $option ) ){
167 0         0 return undef;
168             }
169              
170             # if we find this, grab the short version
171 1 50       4 if ( defined( $self->{long_to_short}{$option} ) ){
172 0         0 $option=$self->{long_to_short}{$option};
173             }
174              
175 1 50       3 if ( !defined( $self->{options}{$option} ) ){
176 0         0 return undef;
177             }
178              
179 1         3 return $self->{options}{$option}{code};
180             }
181              
182             =head2 get_long
183              
184             Returns the long option name for the specified option.
185              
186             One argument is taken and that is the option name.
187              
188             If the option name is not found or is undef,
189             then undef is returned.
190              
191             print 'root: '.$dhcp_options->get_long('root')."\n";
192             print 'mask: '.$dhcp_options->get_long('mask')."\n";
193             print 'mtu: '.$dhcp_options->get_long('mtu')."\n";
194             print 'routers: '.$dhcp_options->get_long('routers')."\n";
195              
196             =cut
197              
198             sub get_long{
199 25     25 1 262 my $self=$_[0];
200 25         32 my $option=$_[1];
201              
202             # need a value to proceed
203 25 50       36 if ( !defined( $option ) ){
204 0         0 return undef;
205             }
206              
207             # if we find this, grab the short version
208 25 50       44 if ( defined( $self->{long_to_short}{$option} ) ){
209 0         0 $option=$self->{long_to_short}{$option};
210             }
211              
212 25 50       41 if ( !defined( $self->{options}{$option} ) ){
213 0         0 return undef;
214             }
215              
216 25         49 return $self->{options}{$option}{long};
217             }
218              
219              
220             =head2 get_multiple
221              
222             Returns if multiple values are supported by this option.
223              
224             0 = single value
225             1 = multiple values
226              
227             One option is taken and that is the option name.
228              
229             If the option name is not found or is undef,
230             then undef is returned.
231              
232             # you can use the long name
233             print 'subnet-mask: '.$dhcp_options->get_multiple('subnet-mask')."\n";
234             # or the easier to remember short name
235             print 'mask: '.$dhcp_options->get_multiple('mask')."\n";
236              
237             if ( $dhcp_options->get_multiple('dns') ){
238             print "Multiple values are supported... exanple\n".
239             "10.10.10.1 , 10.10.10.2\n";
240             }
241              
242             =cut
243              
244             sub get_multiple{
245 1     1 1 259 my $self=$_[0];
246 1         2 my $option=$_[1];
247              
248             # need a value to proceed
249 1 50       5 if ( !defined( $option ) ){
250 0         0 return undef;
251             }
252              
253             # if we find this, grab the short version
254 1 50       3 if ( defined( $self->{long_to_short}{$option} ) ){
255 0         0 $option=$self->{long_to_short}{$option};
256             }
257              
258 1 50       3 if ( !defined( $self->{options}{$option} ) ){
259 0         0 return undef;
260             }
261              
262 1         3 return $self->{options}{$option}{multiple};
263             }
264              
265             =head2 get_options
266              
267             Returns a hash ref with the various options.
268              
269             my $options=$dhcp_options->get_options;
270             foreach my $opt ( keys( %{ $options } ) ){
271             print "----\n".
272             "option: ".$opt."\n".
273             "code: ".$options->{$opt}{'code'}."\n".
274             "multiple: ".$options->{$opt}{'multiple'}."\n".
275             "type: ".$options->{$opt}{'type'}."\n".
276             "long: ".$options->{$opt}{'long'}."\n".
277             }
278              
279             =cut
280              
281             sub get_options{
282 10     10 1 440 return $_[0]->{options};
283             }
284              
285             =head2 get_type
286              
287             Returns the data type that the option in question is.
288              
289             ip = IP address
290             int = integer
291             txt = text field that must be defined
292              
293             One option is taken and that is the option name.
294              
295             If the option name is not found or is undef,
296             then undef is returned.
297              
298             print 'root: '.$dhcp_options->get_type('root')."\n";
299             print 'mask: '.$dhcp_options->get_type('mask')."\n";
300             print 'mtu: '.$dhcp_options->get_type('mtu')."\n";
301              
302             =cut
303              
304             sub get_type{
305 1     1 1 242 my $self=$_[0];
306 1         29 my $option=$_[1];
307              
308             # need a value to proceed
309 1 50       5 if ( !defined( $option ) ){
310 0         0 return undef;
311             }
312              
313             # if we find this, grab the short version
314 1 50       4 if ( defined( $self->{long_to_short}{$option} ) ){
315 0         0 $option=$self->{long_to_short}{$option};
316             }
317              
318 1 50       3 if ( !defined( $self->{options}{$option} ) ){
319 0         0 return undef;
320             }
321              
322 1         3 return $self->{options}{$option}{type};
323             }
324              
325             =head2 valid_option_name
326              
327             This checks if the option name is valid.
328              
329             This checks for possible long and short forms.
330              
331             if ( ! $dhcp_options->valid_option_name( $option ) ){
332             die( $option.' is not a valid option' );
333             }
334              
335              
336             =cut
337              
338             sub valid_option_name{
339 2     2 1 479 my $self=$_[0];
340 2         4 my $option=$_[1];
341              
342 2 50       6 if ( ! defined( $option ) ){
343 0         0 return undef;
344             }
345              
346 2 100 66     10 if (
347             ( defined( $self->{options}{$option} ) ) ||
348             ( defined( $self->{long_to_short}{$option} ) )
349             ){
350 1         3 return 1;
351             }
352              
353 1         2 return undef;
354             }
355              
356             =head2 validate_options
357              
358             This validates a option and the value for it.
359              
360             Twu arguments are taken. The first is the option name
361             and the third is the value.
362              
363             If any issues are found a string is returned that describes it.
364              
365             If there are no issues undef is returned.
366              
367             This should not be mistaken for sanity checking. This just
368             makes sure that the data is the correct type for the option.
369              
370             my $error=$dhcp_options->validate_option( $option, $value );
371             if ( defined( $error ) ){
372             die( $error );
373             }
374              
375             =cut
376              
377             sub validate_option{
378 26     26 0 1938 my $self=$_[0];
379 26         40 my $option=$_[1];
380 26         35 my $value=$_[2];
381              
382             # need a value to proceed
383 26 50       52 if ( !defined( $option ) ){
384 0         0 return 'Option undefined';
385             }
386              
387             # need a value to proceed
388 26 100       40 if ( !defined( $value ) ){
389 1         2 return 'Option Value undefined';
390             }
391              
392             # if we find this, grab the short version
393 25 50       51 if ( defined( $self->{long_to_short}{$option} ) ){
394 0         0 $option=$self->{long_to_short}{$option};
395             }
396              
397             # if this hits, then we don't have a valid name
398 25 50       48 if ( !defined( $self->{options}{$option} ) ){
399 0         0 return '"'.$option.'" was is not a valid option name';
400             }
401              
402 25         40 my $type=$self->{options}{$option}{type};
403              
404             # if it is txt type, we have already checked to make sure
405             # it is defined
406 25 100       79 if ( $type eq 'txt' ){
407 1         3 return undef;
408             }
409              
410             # trans form it into a array to simply processing
411 24         36 my @values;
412 24 100       55 if ( $self->{options}{$option}{multiple} ){
413 20         91 @values=split( /\ *\,\ */, $value );
414             }else{
415             # multiple values are not taken, just shove the
416             # value into the array
417 4         8 push( @values, $value );
418             }
419              
420 24         46 foreach my $test_value ( @values ){
421 38 100       92 if ( $type eq 'int' ){
    50          
422 2 100       13 if ( $test_value !~ /^[0-9]+$/ ){
423 1         4 return "'".$test_value."' is not a valid integer";
424             }
425             }elsif( $type eq 'ip' ){
426 36         45 eval{
427 36         80 my @cidrs=Net::CIDR::addr2cidr($test_value);
428             };
429 36 100       15452 if ( $@ ){
430 2         9 return "'".$test_value."' is not a valid IP";
431             }
432             }
433             }
434              
435 21         61 return undef;
436             }
437              
438             =head1 SUPPORT OPTIONS
439              
440             This only supports the more commonly used one for now and avoids the out of date ones.
441              
442             | Code | Name | Multi | Type | Long Name |
443             |------|------------------|-------|------|---------------------|
444             | 0 | mask | 0 | IP | subnet-mask |
445             | 1 | time-offset | 0 | INT | time-offset |
446             | 3 | routers | 1 | IP | routers |
447             | 4 | ntp | 1 | IP | time-servers |
448             | 6 | dns | 1 | IP | domain-name-servers |
449             | 17 | root | 0 | TXT | root-path |
450             | 26 | mtu | 0 | INT | interface-mtu |
451             | 28 | broadcast | 0 | IP | broadcast-address |
452             | 51 | lease-time | 0 | INT | dhcp-lease-time |
453             | 66 | tfp-server | 0 | TXT | next-server |
454             | 67 | bootfile | 0 | TXT | filename |
455             | 213 | v4-access-domain | 0 | TXT | v4-access-domain |
456             | 252 | web-proxy | 0 | TXT | web-proxy |
457              
458             For options that can take multiple values, /\ *\,\ */ is used for the split.
459              
460             Validation is done as below.
461              
462             INT = /^[0-9]+$/
463             IP = If Net::CIDR::addr2cidr can make sense of it.
464             TXT = defined
465              
466             =head1 AUTHOR
467              
468             Zane C. Bowers-Hadley, C<< >>
469              
470             =head1 BUGS
471              
472             Please report any bugs or feature requests to C, or through
473             the web interface at L. I will be notified, and then you'll
474             automatically be notified of progress on your bug as I make changes.
475              
476              
477              
478              
479             =head1 SUPPORT
480              
481             You can find documentation for this module with the perldoc command.
482              
483             perldoc Net::DHCP::Config::Utilities
484              
485              
486             You can also look for information at:
487              
488             =over 4
489              
490             =item * RT: CPAN's request tracker (report bugs here)
491              
492             L
493              
494             =item * AnnoCPAN: Annotated CPAN documentation
495              
496             L
497              
498             =item * CPAN Ratings
499              
500             L
501              
502             =item * Search CPAN
503              
504             L
505              
506             =back
507              
508              
509             =head1 ACKNOWLEDGEMENTS
510              
511              
512             =head1 LICENSE AND COPYRIGHT
513              
514             This software is Copyright (c) 2019 by Zane C. Bowers-Hadley.
515              
516             This is free software, licensed under:
517              
518             The Artistic License 2.0 (GPL Compatible)
519              
520              
521             =cut
522              
523             1; # End of Net::DHCP::Config::Utilities