Assumptions
First, there are two things you need to be aware of:
- Not all devices respond to ping. Quite a few PC firewalls disable
ping replies. If you're on Ethernet,
arping
can be used instead and
will even detect firewalled PCs.
- dhcpd leaves leases in the file which it /knows/ are no longer valid.
So, here is an example:
lease 192.168.66.132 {
starts 4 2009/01/08 23:58:41;
ends 5 2009/01/09 00:00:41;
binding state free;
hardware ethernet 00:e0:81:28:2d:56;
}
lease 192.168.66.133 {
starts 5 2009/01/09 03:17:17;
ends 2 2038/01/19 03:14:06;
binding state active;
next binding state free;
hardware ethernet 00:e0:81:28:2d:57;
}
You can see that 132 is not in use (binding state free
) and 133 is
(binding state active
). Another possibility is binding state backup
,
but that only occurs in a failover config.
A lease can also be abandoned, which means that the DHCP server was
going to assign that IP, but found it was already in use (via ping).
This is all documented in dhcpd.leases(5)
.
Why are you wanting this?
The DHCP server already re-uses expired leases. Is there a good
reason that you need to check its work? If you're running out of
leases, have you considered lowering the lease time?
Does nmap -sP <start_ip>-<end_ip>
do what you need? That'll also
detect machines with static IP addresses.
Re-writing the question
So, given the above, and assuming you still want this, I'm going to
answer this question instead:
Please write a script to find all leases which are either active or
abandoned and determine if there is currently a machine using that IP
address.
And so:
#!/usr/bin/perl
use File::Slurp qw(slurp);
use Data::Dump qw(pp);
use strict;
1 == @ARGV
or die "Usage: $0 dhpcd.leases\n";
my $leases = slurp($ARGV[0]);
$leases =~ s/^#.*\n//mg;
my @leases = split(/lease (\d.+\d.+\d.+\d+) {/, $leases);
shift @leases;
my %lease = @leases;
while (my ($ip, $rec) = each %lease) {
print $ip;
$rec =~ /^\s*abandoned;\s*$/m and print " abandoned";
$rec =~ /^\s*binding state free;\s*$/m and print " free";
$rec =~ /^\s*binding state active;\s*$/m and print " active";
print "\n";
}
This relatively ugly perl script will give you output like:
192.168.66.132 free
192.168.66.133 active
Which should be pretty easy for you to feed to arping.