parsing dhcpd.leases file

Steve van der Burg steve.vanderburg at LHSC.ON.CA
Wed Apr 15 17:46:04 UTC 2009

>>> Daniel Duarte <dan.r.duarte at> wrote:
> Hello,
> I know this topic has been discussed in the past, and there's lot of
> implementations on the internet, but I would like to explain how I'm
> thinking to parse the dhcpd.leases. I believe there's many with
> experience on this area, and I would like to ear your thoughts about
> this solution.
> Objective:
> - parse periodically the lease file (?every hour? every 10 minutes?),
> in order to load all of the client transactions on a DB;
> - change as little as possible on the DHCP server. All the work should
> be done on another server.
> - avoid duplicate data, and re-parsing the same events more than once;
 (lots of good details snipped)

Doesn't dhcpd.leases contain, right from the point of its creation, all the useful things that were in dhcpd.leases~?

I avoid all that complexity and simply parse the whole file, all 30 megabytes or do (about 12k active leases at the moment) once every 2 minutes on each one of my 3.0.x partner pair servers.  On modern hardware (dual-core AMD Opteron 2200 Sun X4100s running Solaris 10) the parse takes less than 10 seconds to run and introduces no noticeable load on the server.  My code (below) spits out a frozen perl data structure which I then ship off to a central server.


- - - - - - - - - - - -

# Parse the ISC dhcpd leases file, put it into a perl data structure and write it to disk.
# Author: Steve van der Burg <steve.vanderburg at>
#   Date: April 2009

use Date::Parse;
use Data::Dumper;
use strict;

# We set a server name only because we combine the resulting data with lease data from other
# DHCP servers on a central (web) server:

my $pl = make_lease_list((-e "/etc/" ? "dhcp2" : "dhcp1"),

my $flpf = "/some/where/leases-as-perl-data-structure.txt";

if ( $pl && open(FLPF,">$flpf.working") ) {
   $Data::Dumper::Indent = 1;
   print FLPF Dumper($pl);
   close FLPF;
   rename "$flpf.working",$flpf;


sub make_lease_list {
   my ($sname,$lfile) = @_;

   local *LF;
   local $/ = "}\n";

   my %ll;

   return unless open(LF,$lfile);

   while (<LF>) {
      next unless /^lease\s+(\S+)\s+/m;
      my $IP = $1;
      next if /binding state backup/;
      delete $ll{$IP} if exists $ll{$IP} && $ll{$IP}->{server} eq $sname;
      $ll{$IP}->{type}   = "dynamic";
      $ll{$IP}->{state}  = $1  if /binding state\s+([^\;]+)/;
      $ll{$IP}->{MAC}    = $1  if /hardware ethernet\s+([^\;]+)/;
      $ll{$IP}->{uid}    = $1  if /uid\s+([^\;]+)/;
      $ll{$IP}->{chname} = $1  if /client-hostname\s+([^\;]+)/;
      foreach my $time ( qw / starts ends / ) {
         if ( /$time\s+([^\;]+)/ ) {
            my $utm = substr($1,-19);
            $ll{$IP}->{$time} = str2time($utm,"UTC");
      $ll{$IP}->{server} = $sname;
   close LF;

   # Remove all but active leases from the list:
   foreach my $lk ( keys %ll ) {
      delete $ll{$lk}, next unless $ll{$lk}->{state} eq 'active';

   return \%ll;

This information is directed in confidence solely to the person named above and may contain confidential and/or privileged material. This information may not otherwise be distributed, copied or disclosed. If you have received this e-mail in error, please notify the sender immediately via a return e-mail and destroy original message. Thank you for your cooperation.

More information about the dhcp-users mailing list