mirror of
				https://github.com/Telecominfraproject/wlan-lanforge-scripts.git
				synced 2025-11-04 04:38:02 +00:00 
			
		
		
		
	It is quite inefficient and scales badly. Disble this feature and just show the MAC address since we want to be able to call this script often. Signed-off-by: Ben Greear <greearb@candelatech.com>
		
			
				
	
	
		
			222 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/perl
 | 
						|
#
 | 
						|
# Shows current leases.
 | 
						|
#
 | 
						|
# THIS SCRIPT IS PUBLIC DOMAIN, NO RIGHTS RESERVED!
 | 
						|
#
 | 
						|
# I've removed the email addresses of Christian and vom to avoid
 | 
						|
# putting them on spam lists.  If either of you would like to have
 | 
						|
# your email in here please send mail to the DHCP bugs list at ISC.
 | 
						|
#
 | 
						|
# 2008-07-13, Christian Hammers
 | 
						|
#
 | 
						|
# 2009-06-?? - added loading progress counter, pulls hostname, adjusted formatting
 | 
						|
#        vom
 | 
						|
#
 | 
						|
# 2013-04-22 - added option to choose lease file, made manufacture information
 | 
						|
#              optional, sar
 | 
						|
#
 | 
						|
# 2016-01-19 - updated to better trim the manu string and output the hostnames, sar
 | 
						|
#
 | 
						|
# 2016-01-18 - Mainly cosmetics. Eliminated spurious output in "parsable" mode.
 | 
						|
#              Provided for the various conventional lease file locations. (cbp)
 | 
						|
 | 
						|
use strict;
 | 
						|
use warnings;
 | 
						|
use POSIX qw(strftime);
 | 
						|
 | 
						|
my @LEASES = ('/var/db/dhcpd.leases', '/var/lib/dhcp/dhcpd.leases', '/var/lib/dhcp3/dhcpd.leases');
 | 
						|
my @all_leases;
 | 
						|
my @leases;
 | 
						|
 | 
						|
my @OUIS = ('/usr/share/hwdata/oui.txt', '/usr/share/misc/oui.txt', '/usr/local/etc/oui.txt');
 | 
						|
my $OUI_URL = 'http://standards.ieee.org/regauth/oui/oui.txt';
 | 
						|
my $oui;
 | 
						|
 | 
						|
my %data;
 | 
						|
 | 
						|
my $opt_format = 'human';
 | 
						|
my $opt_keep = 'active';
 | 
						|
 | 
						|
our $total_leases = 0;
 | 
						|
 | 
						|
## Return manufactorer name for specified MAC address (aa:bb:cc:dd:ee:ff).
 | 
						|
sub get_manufactorer_for_mac($) {
 | 
						|
    my $manu = "-NA-";
 | 
						|
 | 
						|
    if (defined $oui) {
 | 
						|
	$manu = join('-', ($_[0] =~ /^(..):(..):(..):/));
 | 
						|
	$manu = `grep -i '$manu' $oui | cut -f3`;
 | 
						|
	$manu =~ s/^\s+|\s+$//g;
 | 
						|
    }
 | 
						|
 | 
						|
    return $manu;
 | 
						|
}
 | 
						|
 | 
						|
## Read oui.txt or print warning.
 | 
						|
sub check_oui_file() {
 | 
						|
 | 
						|
    for my $oui_cand (@OUIS) {
 | 
						|
        if ( -r $oui_cand) {
 | 
						|
        $oui = $oui_cand;
 | 
						|
        last;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (not defined $oui) {
 | 
						|
	print(STDERR "To get manufacturer names please download $OUI_URL ");
 | 
						|
	print(STDERR "to /usr/local/etc/oui.txt\n");
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
## Read current leases file into array.
 | 
						|
sub read_dhcpd_leases() {
 | 
						|
 | 
						|
    my $db;
 | 
						|
    for my $db_cand (@LEASES) {
 | 
						|
        if ( -r $db_cand) {
 | 
						|
    $db = $db_cand;
 | 
						|
    last;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    die("Cannot find leases db") unless defined $db;
 | 
						|
    open(F, $db) or die("Cannot open $db: $!");
 | 
						|
    print("Reading leases from $db\n") if $opt_format eq 'human';
 | 
						|
    my $content = join('', <F>);
 | 
						|
    close(F);
 | 
						|
    @all_leases = split(/lease/, $content);
 | 
						|
 | 
						|
    foreach my $lease (@all_leases) {
 | 
						|
    if ($lease =~ /^\s+([\.\d]+)\s+{.*starts \d+ ([\/\d\ \:]+);.*ends \d+ ([\/\d\ \:]+);.*ethernet ([a-f0-9:]+);/s) {
 | 
						|
       ++$total_leases;
 | 
						|
       }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
## Add manufactor name and sort out obsolet assignements.
 | 
						|
sub process_leases() {
 | 
						|
    my $gm_now = strftime("%Y/%m/%d %H:%M:%S", gmtime());
 | 
						|
    my %tmp_leases; # for sorting and filtering
 | 
						|
 | 
						|
    my $counter = $opt_format eq 'human' ? 1 : 0;
 | 
						|
 | 
						|
    # parse entries
 | 
						|
    foreach my $lease (@all_leases) {
 | 
						|
	# skip invalid lines
 | 
						|
	next if not ($lease =~ /^\s+([\.\d]+)\s+{.*starts \d+ ([\/\d\ \:]+);.*ends \d+ ([\/\d\ \:]+);.*ethernet ([a-f0-9:]+);(.*client-hostname \"(\S+)\";)*/s);
 | 
						|
	# skip outdated lines
 | 
						|
	next if ($opt_keep eq 'active'  and  $3 lt $gm_now);
 | 
						|
 | 
						|
	# I like 'human' output, but this part is not helpful when parsing that human output by another script. --Ben
 | 
						|
	#if ($counter) {
 | 
						|
	#    my $percent = (($counter / $total_leases)*100);
 | 
						|
	#    printf "Processing: %2d%% complete\r", $percent;
 | 
						|
	#    ++$counter;
 | 
						|
	#}
 | 
						|
 | 
						|
	my $hostname = "-NA-";
 | 
						|
	if ($6) {
 | 
						|
	    $hostname = $6;
 | 
						|
	}
 | 
						|
 | 
						|
	my $mac = $4;
 | 
						|
	my $date_end = $3;
 | 
						|
	my %entry = (
 | 
						|
	    'ip' => $1,
 | 
						|
	    'date_begin' => $2,
 | 
						|
	    'date_end' => $date_end,
 | 
						|
	    'mac' => $mac,
 | 
						|
	    'hostname' => $hostname,
 | 
						|
# Too slow. --Ben	    'manu' => get_manufactorer_for_mac($mac),
 | 
						|
	    'manu' => "",
 | 
						|
	    );
 | 
						|
 | 
						|
	$entry{'date_begin'} =~ s#\/#-#g; # long live ISO 8601
 | 
						|
	$entry{'date_end'}   =~ s#\/#-#g;
 | 
						|
 | 
						|
	if ($opt_keep eq 'all') {
 | 
						|
	    push(@leases, \%entry);
 | 
						|
	} elsif (not defined $tmp_leases{$mac}  or  $tmp_leases{$mac}{'date_end'} gt $date_end) {
 | 
						|
	    $tmp_leases{$mac} = \%entry;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    # In case we used the hash to filtered
 | 
						|
    if (%tmp_leases) {
 | 
						|
	foreach (sort keys %tmp_leases) {
 | 
						|
	    my $h = $tmp_leases{$_};
 | 
						|
	    push(@leases, $h);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    # print "\n";
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
# Output all valid leases.
 | 
						|
sub output_leases() {
 | 
						|
    if ($opt_format eq 'human') {
 | 
						|
	printf "%-19s%-16s%-15s%-20s%-20s\n","MAC","IP","hostname","valid until","manufacturer";
 | 
						|
	print("===============================================================================================\n");
 | 
						|
    }
 | 
						|
    foreach (@leases) {
 | 
						|
       if ($opt_format eq 'human') {
 | 
						|
	   printf("%-19s%-16s%-14.14s %-20s%-20s\n",
 | 
						|
		  $_->{'mac'},       # MAC
 | 
						|
		  $_->{'ip'},        # IP address
 | 
						|
		  $_->{'hostname'},  # hostname
 | 
						|
		  $_->{'date_end'},  # Date
 | 
						|
		  $_->{'manu'});     # manufactor name
 | 
						|
       } else {
 | 
						|
	   printf("MAC %s IP %s HOSTNAME %s BEGIN %s END %s MANUFACTURER %s\n",
 | 
						|
		  $_->{'mac'},
 | 
						|
		  $_->{'ip'},
 | 
						|
		  $_->{'hostname'},
 | 
						|
		  $_->{'date_begin'},
 | 
						|
		  $_->{'date_end'},
 | 
						|
		  $_->{'manu'});
 | 
						|
       }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
# Commandline Processing.
 | 
						|
sub cli_processing() {
 | 
						|
    while (my $arg = shift(@ARGV)) {
 | 
						|
	if ($arg eq '--help') {
 | 
						|
	    print(
 | 
						|
		"Prints active DHCP leases.\n\n".
 | 
						|
		"Usage: $0 [options]\n".
 | 
						|
		" --help      shows this help\n".
 | 
						|
		" --parsable  machine readable output with full dates\n".
 | 
						|
		" --last      prints the last (even if end<now) entry for every MAC\n".
 | 
						|
		" --all       prints all entries i.e. more than one per MAC\n".
 | 
						|
		" --lease     uses the next argument as the name of the lease file\n".
 | 
						|
		"             the default is to try /var/db/dhcpd.leases then\n".
 | 
						|
		"             /var/lib/dhcp/dhcpd.leases then\n".
 | 
						|
		"             /var/lib/dhcp3/dhcpd.leases\n".
 | 
						|
		"\n");
 | 
						|
	    exit(0);
 | 
						|
	} elsif ($arg eq '--parsable') {
 | 
						|
	    $opt_format = 'parsable';
 | 
						|
	} elsif ($arg eq '--last') {
 | 
						|
	    $opt_keep = 'last';
 | 
						|
	} elsif ($arg eq '--all') {
 | 
						|
	    $opt_keep = 'all';
 | 
						|
	} elsif ($arg eq '--lease') {
 | 
						|
	    unshift @LEASES, shift(@ARGV);
 | 
						|
	} else {
 | 
						|
	    die("Unknown option $arg");
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# main()
 | 
						|
#
 | 
						|
cli_processing();
 | 
						|
#check_oui_file();
 | 
						|
read_dhcpd_leases();
 | 
						|
process_leases();
 | 
						|
output_leases();
 | 
						|
 |