# do_scan
# 
# Input:  hostname or ip
# Output: List of ports found
#
# Performs a full scan of the host.
# Adds host to the database if missing.
# Adds services found to the database if missing.
#
sub do_scan {

   my $host = $_[0];
   my $port = 0;
   my $os = "";

   my @found = ();

   my $svc_str = "INSERT INTO service (ip, port, version) VALUES(?,?,?)";
   my $host_str = "INSERT INTO hosts (ip, hostname, os, admin, email, lastscan, private) VALUES(?,?,?,?,?,?,?)";

   if ($host =~ /\d+\.\d+\.\d+\.\d+/) {
      if ($h = gethost($host)) {
         $host = lc($h->name);
         $ip = inet_ntoa($h->addr);
      }
      else { return undef; }
   }
   else {
      if ($h = gethost($host)) {
         $ip = inet_ntoa($h->addr);
      }
      else { return undef; }
   }


   print STDERR  "Scanning $host [$ip]...";
   open(NMAP, "/usr/local/bin/sudo /usr/local/bin/nmap -F -O $ip |") or return undef;

   while (<NMAP>) {
      if (/^(\d+)\/\w+\s+open\s+(\w+)\s+$/) {
         $port = $1;
         push(@found, $port);
      }
      if (/^Remote operating system guess: (.+)$/) {
         $os = $1;
      }
      if (/^No OS matches for host/) {
         $os = "unknown";
      }
   }

   close(NMAP);
   print STDERR  "Done.  Found $#found ports.\n";


   if (!&host_in_db($ip)) {
  	   &db_connect(0);
      $rv = $dbh->do($host_str, undef, $ip, $host, $os, "unknown", "unknown", time(), undef);
  	   $dbh->disconnect;
   }

   foreach $port (@found) {

      if (!&service_in_db($ip, $port)) {
         &db_connect(0);
         $rv = $dbh->do($svc_str, undef, $ip, $port, "unknown");
         $dbh->disconnect;
      }
   }

   return(@found);

}

# do_scan_ports
# 
# Input:  hostname or ip, port list, type
# Output: List of ports found
#
# Performs a scan of the host on the ports passed
# Adds host to the database if missing.
# Updates host's OS type if changed.
# Adds services found to the database if missing.
#
sub do_scan_ports($@$) {

   my $host = $_[0];
   my @ports = $_[1];
   my $type = $_[2];
   my $os = "";

   my @found = ();

   my $svc_str = "INSERT INTO service (ip, port, version) VALUES(?,?,?)";
   my $host_str = "INSERT INTO hosts (ip, hostname, os, admin, email, lastscan, private) VALUES(?,?,?,?,?,?,?)";

   if ($host =~ /\d+\.\d+\.\d+\.\d+/) {
      if ($h = gethost($host)) {
         $host = lc($h->name);
         $ip = inet_ntoa($h->addr);
      }
      else { return undef; }
   }
   else {
      if ($h = gethost($host)) {
         $ip = inet_ntoa($h->addr);
      }
      else { return undef; }
   }

   my $curr_time = time();

   if ($type) {
      $cmdline = "-O -p ";
   }
   else {
      $cmdline = "-p ";
   }

   foreach $port (@ports) {
      $cmdline = $cmdline . "$port,";
   }
   chop($cmdline);

   print STDERR  "Scanning $host [$ip]...";
   open(NMAP, "/usr/local/bin/sudo /usr/local/bin/nmap $cmdline $ip |");

   while (<NMAP>) {
      if (/^(\d+)\s+open\s+\w+\s+(\w+)\s+$/) {
         $port = $1;
         push(@found, $port);
      }
      if (/^Remote operating system guess: (.+)$/) {
         $os = $1;
      }
      if (/^No OS matches for host/) {
         $os = "unknown";
      }
   }

   close(NMAP);
   print STDERR  "Done.\n";


   if (!&host_in_db($ip)) {
  	   &db_connect(0);
	   $rv = $dbh->do($host_str, undef, $ip, $host, $os, "unknown", "unknown", time(), undef);
  	   $dbh->disconnect;
   }
   elsif ($type && $oldos ne $os) {
	&db_connect(0);
	$rv = $dbh->do("UPDATE hosts SET os = ? WHERE ip = ?",undef,
			$os, $ip);
	$dbh->disconnect;
   }

   foreach $port (@found) {
      if (!&service_in_db($ip, $port)) {
         &db_connect(0);
         $rv = $dbh->do($svc_str, undef, $ip, $port, "unknown");
         $dbh->disconnect;
      }
   }

   return(@found);

}

3;

