sub new { my $invocant = shift; my $class = ref($invocant) || $invocant; my $self = { # Paths for the leases and conf files lease_file => '/var/state/dhcp/dhcpd.leases', conf_file => '/etc/dhcpd.conf', # Hash keyed by dhcpd.conf configuration option # Values contain references to subroutines for handling # each option conf_fields => { host => \&_host, # Static hosts }, # Hash keyed by MAC address # Values contain array of lease arrays leases => { }, @_, }; # Load static hosts &_init_conf($self); bless ($self, $class); return $self; } # Initialize static hosts sub _init_conf { my $self = shift; open CONF, $self->{'conf_file'} or die "Couldn't open ", $self->{'conf_file'}, " $!"; my $option; while () { # If the current line contains an open bracket grab the first word # as the option key $option = $1 if $_ !~ /^\s*#/ && /^\s*(\w+).*{/; # Call the subroutine associated with the current option # Must eval this call in case no such subroutine exists. eval { $self->{'conf_fields'}{$option}->($self, $_) } if $option; # Clear option key if closing bracket $option = undef and eval { $self->{'conf_fields'}{$option}->($self, $_) } if $_ !~ /^\s*#/ && /}/; } close CONF; } # Method to handle static host declarations { my $mac, $ip; sub _host { my $self = shift; # Current line of dhcpd.conf $_ = shift; # Grab MAC address $mac = mac_normal($1) if /\s*hardware ethernet (\w+:\w+:\w+:\w+:\w+:\w+)/; # Grab IP $ip = $1 if /\s*fixed-address (\d+.\d+.\d+.\d+)/; # Push entry onto array of leases for host's MAC # and clear $mac, $ip variables push @{$self->{'leases'}{$mac}}, [ $ip, 'static'] and ($ip, $mac) = ('', '') if /}/ and $ip && $mac; } } #### host camel { hardware ethernet 00:AA:12:BB:A1:34; filename "/default.cfg"; fixed-address 10.1.2.3; }