# Retrieve IP from the connected clients to an AP
# We wait 5 seconds before to ask the AP and to do that we use a thread
# Gerard Alcorlo Bofill

# ALTER TABLE RADLASTAUTH ADD FRAMEDIPADDRESS char(22);

#use strict;
#use warnings;


# MAIN FUNCTION
sub {

   use threads;
   use Net::SNMP;
   use DBI;

   my $mac_hex = ${$_[0]}->get_attr('Calling-Station-Id');

   # Params to be sure we are updating the correct rows
   my $nas_id = ${$_[0]}->get_attr('NAS-IP-Address');
   my $port_id = ${$_[0]}->get_attr('NAS-Port');
   my $session_id = ${$_[0]}->get_attr('Acct-Session-Id');

   if ((! defined $mac_hex) || (! defined $nas_id) || (! defined $port_id) || (! defined $session_id)){
      &main::log($main::LOG_DEBUG, "ERROR: More data needed: mac_hex: $mac_hex, nas_id: $nas_id, port_id: $port_id, session_id: $session_id");
      return;
   }

   # Convet MAC to decimal dotted
   my @chunks = unpack("(A2)*", $mac_hex);

   for (my $i=0; $i<@chunks; $i++){
      $chunks[$i] = hex($chunks[$i]);
   }

   my $mac_int_dotted=join(".",@chunks);

   my $oid = join(".",@chunks);

   my $t = threads->new(

        sub {
           my ($mac_int_dotted, $nas_id, $port_id, $session_id) = @_;

           # Define your NAS IP withe the community
           my %nas = ("192.168.50.9", "secret", "192.168.50.10", "secret", "192.168.50.11", "secret", "192.168.50.12", "secret");

           # Wait for DHCP assignation and the mib value
           sleep (5);

           # Retrieve IP address from the AP using MAC address passed as a dotted decimal OID

           # CISCO-DOT11-ASSOCIATION-MIB
           my $upper_oid="1.3.6.1.4.1.9.9.273.1.2.1.1.16.1.13.101.100.117.114.111.97.109.45.99.101.115.99.97.";

           my $oid_ip = $upper_oid.$mac_int_dotted;

           #&main::log($main::LOG_DEBUG, $oid_ip);

           my ($session, $error) = Net::SNMP->session(
              -hostname    => $nas_id,
              -community   => $nas{"$nas_id"},
              -version     => 'snmpv2c',
           );

           if (!defined $session) {
              #printf "ERROR sessio: %s.\n", $error;
              &main::log($main::LOG_DEBUG, "ERROR: afegeixIP2.pl - error de snmp (sessio) - " . $nas{"$nas_id"}  . "   " . $error);
              return -1;
           }

           my $result = $session->get_request( $oid_ip );

           if (!defined $result) {
              #printf "ERROR get: %s.\n", $session->error();
              &main::log($main::LOG_DEBUG, "ERROR: afegeixIP2.pl - error de snmp (result) - " . $session->error());
              $session->close();
              return -1;
           }

           $session->close();


           my $dec_ip=join '.', unpack "xC*", pack "H*", $result->{$oid_ip};

           # Add the IP address to the RADONLINE table and ACCOUNTING table
           # CHANGE THIS VALUES WITH YOUR OWN VALUES
           my $dbh = DBI->connect('DBI:mysql:radius_cesca:127.0.0.1', 'user', 'password');
           if (! defined $dbh){
              &main::log($main::LOG_DEBUG, "ERROR: afegeixIP2.pl - Could not connect to database: $DBI::errstr");
              return -1;
           }

           my ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
           my $year = 1900 + $yearOffset;

           my $query='UPDATE RADONLINE SET FRAMEDIPADDRESS="'.$dec_ip.'" where NASIDENTIFIER="' . $nas_id . '" and NASPORT=' .
                        $port_id . ' and ACCTSESSIONID="' . $session_id .'"';
           $dbh->do($query);
           &main::log($main::LOG_DEBUG, $query);

           $query='UPDATE ACCOUNTING' . $year . ' SET FRAMEDIPADDRESS="'.$dec_ip.'" where NASIDENTIFIER="' . $nas_id . '" and NASPORT=' .
                        $port_id . ' and ACCTSESSIONID="' . $session_id .'"';
           $dbh->do($query);
           &main::log($main::LOG_DEBUG, $query);

           # Useful to get the FRAMEDIPADDRESS when receiving an Stop
           $query='UPDATE RADLASTAUTH SET FRAMEDIPADDRESS="' . $dec_ip . '", ACCTSESSIONID="' . $session_id. '" where NASIDENTIFIER="' .
                        $nas_id . '" and NASPORT=' . $port_id;
           my $resultat = $dbh->do($query);
           &main::log($main::LOG_DEBUG, $query);

           # It's a PEAP request and data aren't been fullfilled
           if ($resultat != 1){
              $query="INSERT INTO RADLASTAUTH (FRAMEDIPADDRESS, ACCTSESSIONID, NASPORT, NASIDENTIFIER, USERNAME, TIME_STAMP) 
                        VALUES('$dec_ip', '$session_id', $port_id, '$nas_id', 'peap', unix_timestamp(now()))";
              $dbh->do($query);
              &main::log($main::LOG_DEBUG, $query);
           }

           $dbh->disconnect();
        }


   , $oid, $nas_id, $port_id, $session_id);
}


