diff options
Diffstat (limited to 'scripts/dhcp/isc2ippool.pl')
-rwxr-xr-x | scripts/dhcp/isc2ippool.pl | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/scripts/dhcp/isc2ippool.pl b/scripts/dhcp/isc2ippool.pl new file mode 100755 index 0000000..6fb9612 --- /dev/null +++ b/scripts/dhcp/isc2ippool.pl @@ -0,0 +1,189 @@ +#!/usr/bin/perl + +# isc2ippool Insert ISC DHCPD lease entries into SQL database (ippool). +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA +# +# Copyright (C) 2012 Arran Cudbard-Bell (a.cudbardb@freeradius.org) + +use warnings; +use strict; + +use DateTime; +use DateTime::Format::Strptime; +use DateTime::Format::DBI; + +use Getopt::Long; +use Text::DHCPLeases; +use DBI; + +my $lease_file = '/var/db/dhcpd.leases'; +my $sql_type = 'mysql'; +my $sql_host = 'localhost'; +my $sql_user = 'radius'; +my $sql_pass = 'radpass'; +my $sql_database = 'radius'; +my $sql_table = 'dhcpippool'; +my $pool_name = ''; +my $insert_only = 0; + +my $verbose; +my $help; + +sub error { + print STDERR @_, "\n"; + exit(64); +} + +sub notice { + if ($verbose) { + printf(shift . "\n", @_); + } +} + +sub help { + my @this = split('/', $0); + print <<HELP +$this[$#this] [options] <pool> + +Options: + -leases <lease file> - The lease file to parse (defaults to '$lease_file') + -no-update - Don't update existing lease entries + -type - SQL database type (defaults to '$sql_type') + -table - SQL table (defaults to '$sql_table') + -h | -host - SQL host to connect to + -u | -user - SQL user + -p | -pass - SQL password + -v - Verbose + -help - This help text +HELP +; + exit(0); +} + +GetOptions ( + 'leases=s' => \$lease_file, + 'no-update' => \$insert_only, + 'type=s' => \$sql_type, + 'table=s' => \$sql_table, + 'h|host=s' => \$sql_host, + 'u|user=s' => \$sql_user, + 'p|pass=s' => \$sql_pass, + 'v' => \$verbose, + 'help' => \$help +) or error('Failed parsing options'); + +# +# Poolname must be provided, and we need at least some arguments... +# +help if !scalar @ARGV or ($pool_name = $ARGV[$#ARGV]) =~ /^-/; + +-r $lease_file or + error("Lease file ($lease_file) doesn\'t exist or isn't readable"); + +my $leases = Text::DHCPLeases->new(file => $lease_file) or + error("Failed parsing leases file (or lease file empty)"); + +my $handle = DBI->connect( + "DBI:$sql_type:database=$sql_database;host=$sql_host", + $sql_user, $sql_pass, {RaiseError => 1} +); + +my $dt_isc = DateTime::Format::Strptime->new(pattern => '%Y/%m/%d %H:%M:%S'); +my $dt_sql = DateTime::Format::DBI->new($handle); + +for my $lease ($leases->get_objects) { + next unless ($lease->binding_state && $lease->binding_state eq 'active'); + + my($query, @result); + eval { + $query = $handle->prepare(" + SELECT expiry_time, framedipaddress FROM $sql_table + WHERE pool_name = ? + AND pool_key = ?;" + , undef); + + $query->bind_param(1, $pool_name); + $query->bind_param(2, $lease->mac_address); + + $query->execute(); + + @result = $query->fetchrow_array(); + }; + + error($@) if $@; + + my $ends_isc = $dt_isc->parse_datetime($lease->ends =~ m{^(?:[0-9]+) (.+)}); + + if (!$query->rows) { + eval { + $handle->do(" + INSERT INTO $sql_table ( + pool_name, framedipaddress, + expiry_time, pool_key) + VALUES (?, ?, ?, ?);" + , undef + , $pool_name + , $lease->ip_address + , $dt_sql->format_datetime($ends_isc) + , $lease->mac_address + ); + }; + + error($@) if $@; + + notice("MAC:'%s' inserted with IP:'%s'.", + $lease->mac_address, $lease->ip_address); + + next; + } + + my $ends_sql = $dt_sql->parse_datetime($result[0]); + + if ($insert_only && (($result[1] ne $lease->ip_address) || + (DateTime->compare($ends_sql, $ends_isc) < 0))) { + + eval { + $handle->do(" + UPDATE $sql_table + SET + pool_key = ?, expiry_time = ? + WHERE pool_name = ? + AND framedipaddress = ?;" + , undef + , $lease->mac_address + , $dt_sql->format_datetime($ends_isc) + , $pool_name + , $lease->ip_address + ); + }; + + error($@) if $@; + + notice("MAC:'%s' updated. ISC-TS: '%s', SQL-TS: '%s', ISC-IP: '%s', SQL-IP: '%s'.", + $lease->mac_address, + $dt_sql->format_datetime($ends_isc), + $dt_sql->format_datetime($ends_sql), + $lease->ip_address, + $result[1]); + + next; + } + + notice("MAC:'%s' skipped (no update %s). ", + $lease->mac_address, $insert_only ? 'allowed' : 'needed'); +} + +exit(0); |