function collect_mactrack_data($start, $site_id = 0) { global $max_run_duration, $config, $debug, $scan_date; if (defined('CACTI_BASE_PATH')) { $config["base_path"] = CACTI_BASE_PATH; } /* reset the processes table */ db_execute("TRUNCATE TABLE mac_track_processes"); /* dns resolver binary */ $resolver_launched = FALSE; if (read_config_option("mt_reverse_dns") == "on") { $dns_resolver_required = TRUE; }else{ $dns_resolver_required = FALSE; } /* get php binary path */ $command_string = read_config_option("path_php_binary"); /* save the scan date information */ if ($site_id == '') { $scan_date = date("Y-m-d H:i:s"); db_execute("REPLACE INTO settings (name, value) VALUES ('mt_scan_date', '$scan_date')"); } /* just in case we've run too long */ $exit_mactrack = FALSE; /* start mainline processing, order by site_id to keep routers grouped with switches */ if ($site_id > 0) { $device_ids = db_fetch_assoc("SELECT device_id FROM mac_track_devices WHERE site_id='" . $site_id . "' and disabled=''"); }else{ $device_ids = db_fetch_assoc("SELECT device_id FROM mac_track_devices WHERE disabled='' ORDER BY site_id"); } $total_devices = sizeof($device_ids); $concurrent_processes = read_config_option("mt_processes"); if ($debug == TRUE) { $e_debug = " -d"; }else{ $e_debug = ""; } if ($site_id) { $e_site = " -sid=$site_id"; }else{ $e_site = ""; } /* add the parent process to the process list */ db_process_add("-1"); if ($total_devices > 0) { /* grab arpwatch data */ if (read_config_option("mt_arpwatch") == "on") { $arp_db = read_config_option("mt_arpwatch_path"); $delim = read_config_option("mt_mac_delim"); $mac_ip_dns = array(); if (file_exists($arp_db)) { $arp_dat = fopen($arp_db, "r"); if ($arp_dat) { while (!feof($arp_dat)) { $line = fgets($arp_dat, 4096); if ($line != null) { $line = explode (" ", $line); $mac_ad = explode(":",$line[0]); for ($k=0;$k<6;$k++) { $mac_ad[$k] = strtoupper($mac_ad[$k]); if (1 == strlen($mac_ad[$k])) { $mac_ad[$k] = "0" . $mac_ad[$k]; } } /* create the mac address */ $mac = $mac_ad[0] . $delim . $mac_ad[1] . $delim . $mac_ad[2] . $delim . $mac_ad[3] . $delim . $mac_ad[4] . $delim . $mac_ad[5]; /* update the array */ $mac_ip_dns[$mac]["ip"] = $line[1]; $mac_ip_dns[$mac]["dns"] = $line[3]; } } fclose($arp_dat); mactrack_debug("ARPWATCH: IP, DNS & MAC collection complete with ArpWatch"); }else{ cacti_log("ERROR: cannot open file ArpWatch database '$arp_db'");exit; } } } /* scan through all devices */ $j = 0; $i = 0; $last_time = strtotime("now"); $processes_available = $concurrent_processes; while ($j < $total_devices) { /* retreive the number of concurrent mac_track processes to run */ /* default to 10 for now */ $concurrent_processes = db_fetch_cell("SELECT value FROM settings WHERE name='mt_processes'"); for ($i = 0; $i < $processes_available; $i++) { if (($j+$i) >= $total_devices) break; $extra_args = " -q " . $config["base_path"] . "/plugins/mactrack/mactrack_scanner.php -id=" . $device_ids[$i+$j]["device_id"] . $e_debug; mactrack_debug("CMD: " . $command_string . $extra_args); exec_background($command_string, $extra_args); } $j = $j + $i; /* launch the dns resolver if it hasn't been yet */ if (($dns_resolver_required) && (!$resolver_launched)) { sleep(2); exec_background($command_string, " -q " . $config["base_path"] . "/plugins/mactrack/mactrack_resolver.php" . $e_debug . $e_site); $resolver_launched = TRUE; mactrack_debug("DNS Resolver process launched"); } mactrack_debug("A process cycle launch just completed."); /* wait the correct number of seconds for proccesses prior to attempting to update records */ sleep(2); $current_time = strtotime("now"); if (($current_time - $last_time) > read_config_option("mt_dns_prime_interval")) { /* resolve some ip's to mac addresses to let the resolver knock them out */ db_execute("UPDATE mac_track_temp_ports INNER JOIN mac_track_ips ON (mac_track_temp_ports.mac_address=mac_track_ips.mac_address AND mac_track_temp_ports.site_id=mac_track_ips.site_id) SET mac_track_temp_ports.ip_address=mac_track_ips.ip_address, mac_track_temp_ports.updated=1 WHERE mac_track_temp_ports.updated=0 AND mac_track_ips.scan_date='$scan_date'"); mactrack_debug("Interum IP addresses to MAC addresses association pass complete."); $last_time = $current_time; } $processes_running = db_fetch_cell("SELECT count(*) FROM mac_track_processes"); if ($dns_resolver_required) { $processes_available = $concurrent_processes - $processes_running + 1; }else{ $processes_available = $concurrent_processes - $processes_running; } /* take time to check for an exit condition */ list($micro,$seconds) = explode(" ", microtime()); $current = $seconds + $micro; /* exit if we've run too long */ if (($current - $start) > $max_run_duration) { $exit_mactrack = TRUE; cacti_log("ERROR: MacTracking timed out during main script processing.\n"); db_execute("DELETE FROM settings WHERE name='mactrack_process_status'"); db_process_remove("-1"); break; }else{ db_execute("REPLACE INTO settings SET name='mactrack_process_status', value='Total:$total_devices Completed:$j'"); } } /* wait for last process to exit */ $processes_running = db_fetch_cell("SELECT count(*) FROM mac_track_processes WHERE device_id > 0"); while (($processes_running > 0) && (!$exit_mactrack)) { $processes_running = db_fetch_cell("SELECT count(*) FROM mac_track_processes WHERE device_id > 0"); $devices_running = db_fetch_cell("SELECT group_concat(CAST(`device_id` as CHAR) SEPARATOR ', ') as t FROM mac_track_processes;"); /* wait the correct number of seconds for proccesses prior to attempting to update records */ sleep(2); $current_time = strtotime("now"); if (($current_time - $last_time) > read_config_option("mt_dns_prime_interval")) { /* resolve some ip's to mac addresses to let the resolver knock them out */ db_execute("UPDATE mac_track_temp_ports INNER JOIN mac_track_ips ON (mac_track_temp_ports.mac_address=mac_track_ips.mac_address AND mac_track_temp_ports.site_id=mac_track_ips.site_id) SET mac_track_temp_ports.ip_address=mac_track_ips.ip_address, mac_track_temp_ports.updated=1 WHERE mac_track_temp_ports.updated=0 AND mac_track_ips.scan_date='$scan_date'"); mactrack_debug("Interum IP addresses to MAC addresses association pass complete."); } /* take time to check for an exit condition */ list($micro,$seconds) = explode(" ", microtime()); $current = $seconds + $micro; /* exit if we've run too long */ if (($current - $start) > $max_run_duration) { $exit_mactrack = TRUE; cacti_log("ERROR: MacTracking timed out during main script processing.\n"); break; } mactrack_debug("Waiting on " . $processes_running . " with id = [" . $devices_running ."] to complete prior to exiting."); } /* if arpwatch is enabled, let's let it pick up the stragglers, based upon IP address first */ if ((read_config_option("mt_arpwatch") == "on") && (sizeof($mac_ip_dns))) { $ports = db_fetch_assoc("SELECT site_id, device_id, mac_address FROM mac_track_temp_ports WHERE updated=0"); if (sizeof($ports)) { foreach($ports as $port) { if (isset($mac_ip_dns[$port["mac_address"]])) { db_execute("UPDATE mac_track_temp_ports SET updated=1, ip_address='" . $mac_ip_dns[$port["mac_address"]]["ip"] . "'" . ($mac_ip_dns[$port["mac_address"]]["dns"] != '' ? ", dns_hostname='" . $mac_ip_dns[$port["mac_address"]]["dns"] . "'" : "") . " WHERE site_id=" . $port["site_id"] . " AND device_id=" . $port["device_id"] . " AND mac_address='" . $port["mac_address"] . "'"); } } } } /* resolve some ip's to mac addresses to let the resolver knock them out */ db_execute("UPDATE mac_track_temp_ports INNER JOIN mac_track_ips ON (mac_track_temp_ports.mac_address=mac_track_ips.mac_address AND mac_track_temp_ports.site_id=mac_track_ips.site_id) SET mac_track_temp_ports.ip_address=mac_track_ips.ip_address WHERE mac_track_temp_ports.updated=0 AND mac_track_ips.scan_date='$scan_date'"); mactrack_debug("Interum IP addresses to MAC addresses association pass complete."); /* populate the vendor_macs for this pass */ db_execute("UPDATE mac_track_temp_ports SET vendor_mac=SUBSTRING(mac_address,1,8);"); mactrack_debug("MAC addresses to Vendor MACS association pass complete."); /* update the vlan id's table */ db_execute("UPDATE mac_track_vlans SET present='0'"); db_execute("INSERT INTO mac_track_vlans (vlan_id, site_id, device_id, vlan_name, present) SELECT vlan_id, site_id, device_id, vlan_name, '1' AS present FROM mac_track_temp_ports ON DUPLICATE KEY UPDATE vlan_name=VALUES(vlan_name), present=VALUES(present);"); db_execute("DELETE FROM mac_track_vlans WHERE present='0'"); mactrack_debug("MAC VLAN's in VLAN Table Updated."); /* let the resolver know that the parent process is finished and then wait for the resolver if applicable */ db_process_remove("-1"); while (!$exit_mactrack) { /* checking to see if the resolver is running */ $resolver_running = db_fetch_row("SELECT * FROM mac_track_processes WHERE device_id=0"); if (sizeof($resolver_running) == 0) { break; } /* take time to check for an exit condition */ list($micro,$seconds) = explode(" ", microtime()); $current = $seconds + $micro; /* exit if we've run too long */ if (($current - $start) > $max_run_duration) { $exit_mactrack = TRUE; cacti_log("ERROR: MacTracking timed out during main script processing.\n"); break; } } /* transfer temp port results into permanent table */ db_execute("INSERT INTO mac_track_ports (site_id, device_id, hostname, dns_hostname, device_name, vlan_id, vlan_name, mac_address, vendor_mac, ip_address, port_number, port_name, scan_date, authorized) SELECT site_id, device_id, hostname, dns_hostname, device_name, vlan_id, vlan_name, mac_address, vendor_mac, ip_address, port_number, port_name, scan_date, authorized FROM mac_track_temp_ports ON DUPLICATE KEY UPDATE site_id=VALUES(site_id), hostname=VALUES(hostname), device_name=VALUES(device_name), vlan_id=VALUES(vlan_id), vlan_name=VALUES(vlan_name), vendor_mac=VALUES(vendor_mac), ip_address=VALUES(ip_address), dns_hostname=VALUES(dns_hostname), port_name=VALUES(port_name), authorized=VALUES(authorized)"); mactrack_debug("Finished transferring scan results to main table."); /* transfer the subnet information, although primative, into the ip_ranges table */ $ip_ranges = db_fetch_assoc("SELECT SUBSTRING_INDEX(`ip_address`,'.',3) AS ip_range, site_id, COUNT(DISTINCT ip_address) AS ips_current, scan_date AS ips_current_date FROM mac_track_temp_ports WHERE ip_address != '' GROUP BY ip_range, site_id"); if (is_array($ip_ranges)) { foreach($ip_ranges as $ip_range) { $range_record = db_fetch_row("SELECT * FROM mac_track_ip_ranges WHERE ip_range='" . $ip_range["ip_range"] . "' AND site_id='" . $ip_range["site_id"] . "'"); if (sizeof($range_record) == 0) { db_execute("REPLACE INTO `mac_track_ip_ranges` (ip_range, site_id, ips_current, ips_current_date) VALUES ('" . $ip_range["ip_range"] . "'," . $ip_range["site_id"] . ",'" . $ip_range["ips_current"] . "','" . $ip_range["ips_current_date"] . "')"); }else{ db_execute("UPDATE `mac_track_ip_ranges` SET ips_current='" . $ip_range["ips_current"] . "', " . "ips_current_date='" . $ip_range["ips_current_date"] . "'" . "WHERE ip_range='" . $range_record["ip_range"] . "' AND " . "site_id='" . $range_record["site_id"] . "'"); } } } /* update the max values if required */ db_execute("UPDATE `mac_track_ip_ranges` SET ips_max=ips_current, ips_max_date=ips_current_date WHERE ips_current > ips_max"); /* collect statistics */ if ($site_id == 0) { $stats = db_fetch_assoc("SELECT site_id, count(device_id) as total_devices, sum(ports_active) as total_oper_ports, sum(macs_active) as total_macs, sum(ports_total) as total_user_ports FROM mac_track_devices GROUP BY site_id"); }else{ $stats = db_fetch_assoc("SELECT site_id, count(device_id) as total_devices, sum(ports_active) as total_oper_ports, sum(macs_active) as total_macs, sum(ports_total) as total_user_ports FROM mac_track_devices WHERE site_id='$site_id' GROUP BY site_id"); } /* collect total device errors */ $errors = db_fetch_assoc("SELECT site_id, snmp_status, count(device_id) as total_device_errors FROM mac_track_devices GROUP BY site_id, snmp_status"); $ips = array_rekey(db_fetch_assoc("SELECT site_id, count(ip_address) as total_ips FROM mac_track_ips WHERE scan_date='$scan_date' GROUP BY site_id"), "site_id", "total_ips"); foreach($errors as $error) { if (!isset($error_count[$error["site_id"]])) { $error_count[$error["site_id"]] = 0; } if ($error["snmp_status"] <> 3) { $error_count[$error["site_id"]] += $error["total_device_errors"]; } } foreach($stats as $stat) { $num_ips = @$ips[$stat["site_id"]]; if (empty($num_ips)) $num_ips = 0; $update_string = "UPDATE mac_track_sites SET " . "total_devices='" . $stat["total_devices"] . "', " . "total_ips='" . $num_ips . "', " . "total_macs='" . $stat["total_macs"] . "', " . "total_oper_ports='" . $stat["total_oper_ports"] . "', " . "total_user_ports='" . $stat["total_user_ports"] . "', " . "total_device_errors='" . $error_count[$stat["site_id"]] . "' " . "WHERE site_id='" . $stat["site_id"] . "'"; db_execute($update_string); } mactrack_debug("Finished updating site table with collection statistics."); /* process macwatch data */ $macwatches = db_fetch_assoc("SELECT * FROM mac_track_macwatch"); if (sizeof($macwatches)) { $from = read_config_option("mt_from_email"); $fromname = read_config_option("mt_from_name"); foreach($macwatches as $record) { /* determine if we should check this one */ $found = db_fetch_row("SELECT * FROM mac_track_temp_ports WHERE mac_address='" . $record["mac_address"] . "'"); if (sizeof($found)) { /* set the subject */ $subject = "MACAUTH Notification: Mac Address '" . $record["mac_address"] . "' Found, For: '" . $record["name"] . "'"; /* set the message with replacements */ $message = str_replace("<IP>", $found["ip_address"], $record["description"]); $message = str_replace("<MAC>", $found["mac_address"], $message); $message = str_replace("<TICKET>", $record["ticket_number"], $message); $message = str_replace("<SITENAME>", db_fetch_cell("SELECT site_name FROM mac_track_sites WHERE site_id=" . $found["site_id"]), $message); $message = str_replace("<DEVICEIP>", $found["hostname"], $message); $message = str_replace("<DEVICENAME>", $found["device_name"], $message); $message = str_replace("<PORTNUMBER>", $found["port_number"], $message); $message = str_replace("<PORTNAME>", $found["port_name"], $message); /* send out the email */ if (!$record["discovered"] || $record["notify_schedule"] >= "2") { $mail = true; if ($record["notify_schedule"] > 2) { if (strtotime($record["date_last_notif"]) + $record["notify_schedule"] > time()) { $mail = false; } } if ($mail) { mactrack_mail($record["email_addresses"], $from, $fromname, $subject, $message, $headers = ''); } } /* update the the correct information */ db_execute("UPDATE mac_track_macwatch SET discovered=1, date_last_seen=NOW()" . (strtotime($record["date_first_seen"]) == 0 ? ", date_first_seen=NOW()":"") . " WHERE mac_address='" . $record["mac_address"] . "'"); } } } /* process macauth data */ $mac_auth_frequency = read_config_option("mt_macauth_email_frequency"); if ($mac_auth_frequency != "disabled") { $last_macauth_time = read_config_option("mt_last_macauth_time"); /* if it's time to e-mail */ if (($last_macauth_time + ($mac_auth_frequency*60) > time()) || ($mac_auth_frequency == 0)) { mactrack_process_mac_auth_report($mac_auth_frequency, $last_macauth_time); } } /* process aggregated data */ db_execute("UPDATE mac_track_aggregated_ports SET active_last=0;"); db_execute("INSERT INTO mac_track_aggregated_ports (site_id, device_id, hostname, device_name, vlan_id, vlan_name, mac_address, vendor_mac, ip_address, dns_hostname, port_number, port_name, date_last, first_scan_date, count_rec, active_last, authorized) SELECT site_id, device_id, hostname, device_name, vlan_id, vlan_name, mac_address, vendor_mac, ip_address, dns_hostname, port_number, port_name, scan_date, scan_date, 1, 1, authorized FROM mac_track_temp_ports ON DUPLICATE KEY UPDATE count_rec=count_rec+1, active_last=1, date_last=mac_track_temp_ports.scan_date"); /* purge the ip address and temp port table */ db_execute("TRUNCATE TABLE mac_track_temp_ports"); db_execute("DELETE FROM mac_track_ips WHERE scan_date<'$scan_date'"); db_execute("OPTIMIZE TABLE mac_track_ips"); db_execute("TRUNCATE TABLE mac_track_scan_dates"); db_execute("REPLACE INTO mac_track_scan_dates (SELECT DISTINCT scan_date from mac_track_ports);"); }else{ cacti_log("NOTE: MACTRACK has no devices to process at this time\n"); } }
case "-h": case "-v": case "--version": case "--help": display_help(); exit; default: print "ERROR: Invalid Parameter " . $parameter . "\n\n"; display_help(); exit; } } /* place a process marker in the database */ if (!$test_mode) { db_process_add($device_id, TRUE); } /* get device information */ $device = db_fetch_row("SELECT * FROM mac_track_devices WHERE device_id =" . $device_id); if (sizeof($device) == 0) { mactrack_debug("ERROR: Device with Id of '$device_id' not found in database. Can not continue."); db_process_remove($device_id); exit; } /* get the site name */ $site = db_fetch_cell("SELECT site_name FROM mac_track_sites WHERE site_id ='" . $device["site_id"] . "'"); if (strlen($site) == 0) { mactrack_debug("ERROR: Site not found in database. Can not continue."); db_process_remove($device_id);
exit; } } } /* check if you need to run or not */ if (read_config_option('mt_reverse_dns') == 'on') { $timeout = read_config_option('mt_dns_timeout'); $dns_primary = read_config_option('mt_dns_primary'); $dns_secondary = read_config_option('mt_dns_secondary'); $primary_down = FALSE; $secondary_down = FALSE; } else { exit; } /* place a process marker in the database for the ip resolver */ db_process_add(0, TRUE); if ($site_id != '') { $sql_where = 'AND site_id=$site_id'; } else { $sql_where = ''; } /* loop until you are it */ while (1) { $processes_running = db_fetch_cell('SELECT COUNT(*) FROM mac_track_processes WHERE device_id != 0'); $run_status = db_fetch_assoc("SELECT last_rundate,\n\t\tCOUNT(last_rundate) AS devices\n\t\tFROM mac_track_devices\n\t\tWHERE disabled = ''\n\t\t{$sql_where}\n\t\tGROUP BY last_rundate\n\t\tORDER BY last_rundate DESC"); if (sizeof($run_status) == 1 && $processes_running == 0) { $break = TRUE; } else { $break = FALSE;