#!/usr/bin/perl -w
#Script for adding subnet configuration information into DHCP PostgreSQL database
#Writen by Chebotarev Roman (15.06.2009)

use strict;
use DBI;

if( scalar(@ARGV) < 8)
{
    print "Usage: $0 Default-GW GIAddr NetMask Server-ID Interface-ID Domain-Name Lease-Time Client-Subnet [DNS-1] [DNS-2] [DNS-3]\n";
    exit;
}


#Start 
	my $i = 0;
	my $default_gw = $ARGV[$i++];
	my $giaddr = $ARGV[$i++];
	my $netmask = $ARGV[$i++];
	my $server_id = $ARGV[$i++];
	my $server_addr = $ARGV[$i++];
	my $domain_name = $ARGV[$i++];
	my $lease_time = $ARGV[$i++];
	my $client_subnet = ip_to_int($ARGV[$i++]);
	my @dns = ($ARGV[$i++], $ARGV[$i++], $ARGV[$i++]);
	my $dns_servers = '';
	foreach my $dns (@dns)
	{
	    $dns_servers .= sprintf("%02x%02x%02x%02x", split(/\./, $dns)) if defined $dns;
	}

	my %attributes = (  'DHCP-Router-Address' => sprintf("0x%02x%02x%02x%02x", split(/\./, $default_gw)), 
						'DHCP-Gateway-IP-Address' => $giaddr, 
						'DHCP-Interface-Index' => $server_addr,
						'DHCP-Subnet-Mask' => $netmask, 
						'DHCP-DHCP-Server-Identifier' => $server_id, 
						'DHCP-Domain-Name' => $domain_name, 
						'DHCP-IP-Address-Lease-Time' => $lease_time,
						'DHCP-MS-Static-Routes' => '0x'.option_249($default_gw),
						'DHCP-Rebinding-Time' => int($lease_time * 0.9),
						'DHCP-Renewal-Time' => int($lease_time * 0.875)
						);
	$attributes{'DHCP-Domain-Name-Server'} = "0x$dns_servers" if length $dns_servers;

	my ($query, $sth, $rv);
	my ($ip, $inp, $outp);
	my $attribute;
	my $db_name = 'dhcp';
	my $user = 'radius';
	my $passwd = '';

	my $db = DBI->connect("dbi:Pg:dbname=$db_name",$user,"", {PrintError => 0});

	if (defined($DBI::err)) 
	{
		print $DBI::errstr . "\n";
		exit($DBI::err);
	}

	foreach $attribute (keys(%attributes))
	{
		$query = "INSERT INTO interfaces (server_addr, attribute, value, client_subnet) ".    
						"values(".ip_to_int($server_addr).", '$attribute', '$attributes{$attribute}', $client_subnet)";
		print "QUERY: $query\n";
		$sth = $db->prepare($query);
		$rv = $sth->execute();
		if (!defined $rv) 
		{
			print "ERROR executing query '$query' : " . $db->errstr . "\n";
			last;
		}else {print "OK\n";}
	}
	$sth->finish();
	#Disconnect from DB
	$db->disconnect();
#End
sub ip_to_int
{
	my @octs = ($_[0] =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/);

	my $int_id = $octs[0] << 24;
	$int_id += $octs[1] << 16;
	$int_id += $octs[2] << 8;
	$int_id += $octs[3];
	return $int_id;
}


sub option_249 {
	my @subnets = qw#10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 194.154.83.0/24 
					81.211.62.0/24 213.33.170.0/24 81.25.48.0/22 81.25.52.0/24 
					81.25.53.0/27 81.25.54.0/24 81.25.55.0/24#;
	my $gw = $_[0];
    my @bytes = ();
    my $out_str = '';
    my ($subnet, $mask, $b0, $b1, $b2, $b3);
    foreach my $route (@subnets) 
	{
        ($subnet,  $mask) = split('/', $route);
        ($b0, $b1, $b2, $b3) = split(/\./, $subnet);
        $out_str .= sprintf('%02x', $mask);
        $out_str .= sprintf('%02x', $b0);
        $out_str .= sprintf('%02x', $b1) if($mask > 8);
        $out_str .= sprintf('%02x', $b2) if($mask > 16);
        $out_str .= sprintf('%02x', $b3) if($mask > 24);
		$out_str .= sprintf('%02x%02x%02x%02x', split(/\./, $gw));
=c        ($b0, $b1, $b2, $b3) = split(/\./, $gw);
        $out_str .= sprintf('%02x', $b0);
        $out_str .= sprintf('%02x', $b1);
        $out_str .= sprintf('%02x', $b2);
        $out_str .= sprintf('%02x', $b3);
=cut
    }
    return $out_str;
}

=c
sub option_249 
{
	my @subnets = qw#10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 194.154.83.0/24 
					81.211.62.0/24 213.33.170.0/24 81.25.48.0/22 81.25.52.0/24 
					81.25.53.0/27 81.25.54.0/24 81.25.55.0/24#;
	my $router = $_[0];
	my $out_str .= '';
    my ($b0, $b1, $b2, $b3) = split(/\./, $router);
	my ($subnet, $mask);
    $out_str = sprintf('%02x', $b0);
    $out_str .= sprintf('%02x', $b1);
    $out_str .= sprintf('%02x', $b2);
    $out_str .= sprintf('%02x', $b3);
    foreach my $route (@subnets) 
	{
		($subnet, $mask) = split('/', $route);
		($b0, $b1, $b2, $b3) = split(/\./, $subnet);
		$out_str .= sprintf('%02x', $mask);
		$out_str .= sprintf('%02x', $b0);
		$out_str .= sprintf('%02x', $b1) if($mask > 8);
		$out_str .= sprintf('%02x', $b2) if($mask > 16);
		$out_str .= sprintf('%02x', $b3) if($mask > 24);
	}
	return $out_str;
}

=cut
