File Coverage

blib/lib/Net/DHCP/Info.pm
Criterion Covered Total %
statement 51 59 86.4
branch 29 44 65.9
condition n/a
subroutine 7 8 87.5
pod 4 4 100.0
total 91 115 79.1


line stmt bran cond sub pod time code
1             package Net::DHCP::Info;
2              
3             =head1 NAME
4              
5             Net::DHCP::Info - Fast dhcpd.leases and dhcpd.conf parser
6              
7             =head1 NOTE
8              
9             =head2 DEPRECATED
10              
11             This module is not very flexible, and not maintained.
12             Use L<Net::ISC::DHCPd> instead.
13              
14             =head1 VERSION
15              
16             Version 0.11
17              
18             =head1 SYNOPSIS
19              
20             use Net::DHCP::Info;
21              
22             my $conf = Net::DHCP::Info->new($path_to_dhcpd_conf);
23             my $lease = Net::DHCP::Info->new($path_to_dhcpd_leases);
24              
25             while(my $net = $conf->fetch_subnet) {
26             # .. do stuff with $net
27             }
28              
29             while(my $lease = $lease->fetch_lease) {
30             # .. do stuff with $lease
31             }
32              
33             =cut
34              
35 4     4   54601 use strict;
  4         7  
  4         225  
36 4     4   27 use warnings;
  4         6  
  4         112  
37 4     4   2599 use Net::DHCP::Info::Obj;
  4         10  
  4         45  
38              
39             our $VERSION = '0.12';
40             our $FIND_NET = qr{^([^s]*)subnet\s+([\d\.]+)\s+netmask\s+([\d\.]+)};
41             our $ROUTERS = qr{^\W*option\s+routers\s+([\d\.\s]+)};
42             our $RANGE = qr{^\W*range\s+([\d\.]+)\s*([\d\.]*)};
43             our $FIND_LEASE = qr{^lease\s([\d\.]+)};
44             our $STARTS = qr{^\W+starts\s\d+\s(.+)};
45             our $ENDS = qr{^\W+ends\s\d+\s(.+)};
46             our $HW_ETHERNET = qr{^\W+hardware\sethernet\s(.+)};
47             our $REMOTE_ID = qr{option\sagent.remote-id\s(.+)};
48             our $BINDING = qr{^\W+binding\sstate\s(.+)};
49             our $HOSTNAME = qr{^\W+client-hostname\s\"([^"]+)\"};
50             our $CIRCUIT_ID = qr{^\W+option\sagent.circuit-id\s(.+)};
51             our $END = qr{^\}$};
52              
53             my %stash;
54              
55             =head2 METHODS
56              
57             =head2 new($file)
58              
59             Object constructor. Takes one argument; a filename to parse. This can be
60             either a dhcpd.conf or dhcpd.leases file.
61              
62             =cut
63              
64             sub new {
65 3     3 1 44 my $class = shift;
66 3         9 my $file = shift;
67              
68 3 50       17 if(ref $file eq 'GLOB') {
69 3         17 return bless $file, $class;
70             }
71             else {
72 0 0       0 return 'file does not exist' unless(-f $file);
73 0 0       0 return 'file is not readable' unless(-r $file);
74 0 0       0 open(my $self, '<', $file) or return $!;
75 0         0 return bless $self, $class;
76             }
77             }
78              
79             =head2 fetch_subnet
80              
81             This method returns an object of the C<Net::DHCP::Info::Obj> class.
82              
83             =cut
84              
85             sub fetch_subnet {
86 1     1 1 674 my $self = shift;
87 1         2 my $tab = "";
88 1         2 my $net;
89              
90             FIND_NET:
91 1         14 while(readline $self) {
92 2 100       23 if(my($tab, @ip) = /$FIND_NET/mx) {
93 1         27 $net = Net::DHCP::Info::Obj->new(@ip);
94 1         226 last FIND_NET;
95             }
96             }
97              
98             READ_NET:
99 1         9 while(readline $self) {
100              
101 4         31 s/\;//mx;
102              
103 4 100       67 if(/$ROUTERS/mx) {
    100          
    100          
104 1         9 $net->routers([ split /\s+/mx, $1 ]);
105             }
106             elsif(my @net = /$RANGE/mx) {
107 1 50       6 $net[1] = $net[0] unless($net[1]);
108 1         5 $net->add_range(\@net);
109             }
110             elsif(/$tab\}/mx) {
111 1         4 last READ_NET;
112             }
113             }
114              
115 1 50       4 return ref $net ? $net : undef;
116             }
117              
118             =head2 fetch_lease
119              
120             This method returns an object of the C<Net::DHCP::Info::Obj> class.
121              
122             =cut
123              
124             sub fetch_lease {
125 2     2 1 8920 my $self = shift;
126 2         7 my $lease;
127              
128             FIND_LEASE:
129 2         41 while(readline $self) {
130 2 50       29 if(my($ip) = /$FIND_LEASE/mx) {
131 2         60 $lease = Net::DHCP::Info::Obj->new($ip);
132 2         352 last FIND_LEASE;
133             }
134             }
135              
136             READ_LEASE:
137 2         22 while(readline $self) {
138              
139 14         47 s/\;//mx;
140              
141 14 100       311 if(/$STARTS/mx) {
    100          
    100          
    50          
    50          
    100          
    100          
    100          
142 2         14 $lease->starts($1);
143             }
144             elsif(/$ENDS/mx) {
145 2         12 $lease->ends($1);
146             }
147             elsif(/$HW_ETHERNET/mx) {
148 2         10 $lease->mac( fixmac($1) );
149             }
150             elsif(/$REMOTE_ID/mx) {
151 0         0 $lease->remote_id( fixmac($1) );
152             }
153             elsif(/$CIRCUIT_ID/mx) {
154 0         0 $lease->circuit_id( fixmac($1) );
155             }
156             elsif(/$BINDING/mx) {
157 2         10 $lease->binding($1);
158             }
159             elsif(/$HOSTNAME/mx) {
160 2         11 $lease->hostname($1);
161             }
162             elsif(/$END/mx) {
163 2         5 last READ_LEASE;
164             }
165             }
166              
167 2 50       15 return ref $lease ? $lease : undef;
168             }
169              
170             =head1 FUNCTIONS
171              
172             =head2 fixmac
173              
174             Takes a mac in various formats as an argument, and returns it as a 12 char
175             string.
176              
177             =cut
178              
179             sub fixmac {
180 2     2 1 7 my $mac = shift;
181              
182 2 50       12 $mac = unpack('H*', $mac) if($mac =~ /[\x00-\x1f]/mx);
183 2         7 $mac =~ y/a-fA-F0-9\://cd;
184 12         499 $mac = join "", map {
185 2         14 my $i = 2 - length($_);
186 12 50       46 ($i < 0) ? $_ : ("0" x $i) .$_;
187             } split /:/mx, $mac;
188              
189 2         16 return $mac;
190             }
191              
192             sub DESTROY {
193 0     0     my $self = shift;
194 0           delete $stash{$self};
195             }
196              
197             =head1 AUTHOR
198              
199             Jan Henning Thorsen, C<< <pm at flodhest.net> >>
200              
201             =head1 COPYRIGHT & LICENSE
202              
203             Copyright 2007 Jan Henning Thorsen, all rights reserved.
204              
205             This program is free software; you can redistribute it and/or modify it
206             under the same terms as Perl itself.
207              
208             =cut
209              
210             1;