diff --git a/html/css/bootstrap.css b/html/css/bootstrap.css index dfe5bfb..a57f954 100644 --- a/html/css/bootstrap.css +++ b/html/css/bootstrap.css @@ -1314,3 +1314,4 @@ th.visible-print,td.visible-print{display:none !important;} .dl-search{margin-bottom:0px;margin-top:0px;} .dl-search dt{float:left;width:48px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;} .dl-search dd{margin-left:65px;} +.clientconnected {color:#008c00;} diff --git a/html/includes/graphs/device/wifi_client.inc.php b/html/includes/graphs/device/wifi_client.inc.php new file mode 100644 index 0000000..5b77b81 --- /dev/null +++ b/html/includes/graphs/device/wifi_client.inc.php @@ -0,0 +1,32 @@ + diff --git a/html/includes/graphs/device/wifi_clients.inc.php b/html/includes/graphs/device/wifi_clients.inc.php index 67817b2..e6a089e 100644 --- a/html/includes/graphs/device/wifi_clients.inc.php +++ b/html/includes/graphs/device/wifi_clients.inc.php @@ -7,22 +7,33 @@ $rrd_options .= " -l 0 -E "; $radio1 = $config['rrd_dir'] . "/".$device['hostname']."/wificlients-radio1.rrd"; $radio2 = $config['rrd_dir'] . "/".$device['hostname']."/wificlients-radio2.rrd"; +if ($device['os'] == "ios") +{ + $radio1_name = "'Clients on 2.4GHz '"; + $radio2_name = "'Clients on 5GHz '"; +} +else +{ + $radio1_name = "'Clients on Radio1 '"; + $radio2_name = "'Clients on Radio2 '"; +} + if (file_exists($radio1)) { $rrd_options .= " COMMENT:' Cur Min Max\\n'"; $rrd_options .= " DEF:wificlients1=".$radio1.":wificlients:AVERAGE "; - $rrd_options .= " LINE1:wificlients1#CC0000:'Clients on Radio1 ' "; + $rrd_options .= " LINE1:wificlients1#CC0000:".$radio1_name." "; $rrd_options .= " GPRINT:wificlients1:LAST:%3.0lf "; $rrd_options .= " GPRINT:wificlients1:MIN:%3.0lf "; $rrd_options .= " GPRINT:wificlients1:MAX:%3.0lf\\\l "; if (file_exists($radio2)) { $rrd_options .= " DEF:wificlients2=".$radio2.":wificlients:AVERAGE "; - $rrd_options .= " LINE1:wificlients2#008C00:'Clients on Radio2 ' "; + $rrd_options .= " LINE1:wificlients2#008C00:".$radio2_name." "; $rrd_options .= " GPRINT:wificlients2:LAST:%3.0lf "; $rrd_options .= " GPRINT:wificlients2:MIN:%3.0lf "; $rrd_options .= " GPRINT:wificlients2:MAX:%3.0lf\\\l "; } } -// EOF +?> diff --git a/html/includes/navbar.inc.php b/html/includes/navbar.inc.php index c9c60ff..f16f011 100644 --- a/html/includes/navbar.inc.php +++ b/html/includes/navbar.inc.php @@ -211,6 +211,8 @@ foreach ($config['device_types'] as $devtype) } ?>
  • +
  • WiFi Clients
  • +
  • Add Device
  • Delete Device
  • diff --git a/html/pages/device/graphs.inc.php b/html/pages/device/graphs.inc.php index 96300c8..69cd939 100644 --- a/html/pages/device/graphs.inc.php +++ b/html/pages/device/graphs.inc.php @@ -50,10 +50,61 @@ foreach ($graph_enable as $graph => $entry) $graph_array = array(); if ($graph_enable[$graph]) { - $graph_title = $config['graph_types']['device'][$graph]['descr']; - $graph_array['type'] = "device_" . $graph; + if ($graph == 'wifi_client') + { + $graph_array['device'] = $device['device_id']; + $graph_array['os'] = $device['os']; - include("includes/print-device-graph.php"); + if ($graph_array['os'] == "ios") + { + // Get a list of clients associated with this Cisco Aironet access point + $clients = dbFetchRows("SELECT device_id, client_ip, active FROM aironet_clients WHERE device_id='".$device['device_id']."'"); + + foreach ($clients as $client) + { + $client_ip = $client['client_ip']; + + $client_id = gethostbyaddr($client_ip); + + $graph_array['aironet_ap'] = $device['hostname']; + $graph_array['client_ip'] = $client_ip; + $graph_array['type'] = "device_" . $graph; + if ($client['active'] == 'y') + { + $active = 'class="clientconnected"'; + } + else + { + unset($active); + } + + + // FIXME not css alternating yet + if (is_integer($g_i/2)) { $row_colour = $list_colour_a; } else { $row_colour = $list_colour_b; } + + echo(''); + + $url = generate_url(array('page' => 'wifi_client', + 'client' => $client_ip)); + echo('

    + Client '.$client_id.' +

    '); + + include("includes/print-graphrow.inc.php"); + + echo(''); + + $g_i++; + } + } + } + else + { + $graph_title = $config['graph_types']['device'][$graph]['descr']; + $graph_array['type'] = "device_" . $graph; + + include("includes/print-device-graph.php"); + } } } diff --git a/html/pages/device/overview.inc.php b/html/pages/device/overview.inc.php index ff8594e..e2f5d90 100644 --- a/html/pages/device/overview.inc.php +++ b/html/pages/device/overview.inc.php @@ -117,6 +117,8 @@ include("overview/toner.inc.php"); include("overview/sensors.inc.php"); +include("overview/wificlients.inc.php"); + include("overview/events.inc.php"); ?> diff --git a/html/pages/device/overview/wificlients.inc.php b/html/pages/device/overview/wificlients.inc.php new file mode 100644 index 0000000..de95892 --- /dev/null +++ b/html/pages/device/overview/wificlients.inc.php @@ -0,0 +1,60 @@ + +
    +
    + WiFi Clients
    +
    + '); + echo(' + Client + SSID + Radio + Signal (dBm) + Quality (dBm) + '); + foreach ($clients as $client) + { + if ($client['active'] == 'y') + { + $active = 'class="clientconnected"'; + } + else + { + unset($active); + } + + $client_id = gethostbyaddr($client['client_ip']); + + $url = generate_url(array('page' => 'wifi_client', + 'client' => $client['client_ip'])); + switch ($client['radio']) + { + case 1: + $freq = '2.4GHz'; + break; + + case 2: + $freq = '5GHz'; + break; + } + echo(' + '.$client_id.' + '.$client['ssid'].' + '.$freq.' + '.($client['active'] == 'y' ? $client['signal_db'] : '-').' + '.($client['active'] == 'y' ? $client['quality_db'] : '-').' + '); + } + echo(''); + } + echo("
    "); +?> diff --git a/html/pages/wifi_client.inc.php b/html/pages/wifi_client.inc.php new file mode 100644 index 0000000..6083e97 --- /dev/null +++ b/html/pages/wifi_client.inc.php @@ -0,0 +1,130 @@ +'); + echo(' + + + Client '.$client_id.' + + '); + echo(''); + + foreach ($aps as $ap) + { + unset($graph_array); + $ap_device = device_by_id_cache($ap['device_id']); + $graph_array['os'] = $ap_device['os']; + $graph_array['aironet_ap'] = $ap_device['hostname']; + $graph_array['client_ip'] = $ap['client_ip']; + $graph_array['type'] = "device_wifi_client"; + if ($ap['active'] == 'y') + { + $active = 'class="clientconnected"'; + } + else + { + unset($active); + } + + // FIXME not css alternating yet + if (is_integer($g_i/2)) { $row_colour = $list_colour_a; } else { $row_colour = $list_colour_b; } + + echo(''); + + $url = generate_url(array('page' => 'device', + 'device' => $ap_device['device_id'], + 'tab' => 'graphs', + 'group' => 'wireless')); + echo('

    + Basestation '.$ap_device['hostname'].' +

    '); + + include("includes/print-graphrow.inc.php"); + + echo(''); + + $g_i++; + } + + return; +} + +function display_all_clients() +{ + // Get a list of unique clients + $clients= dbFetchRows("SELECT DISTINCT client_ip FROM aironet_clients"); + + // Print the device header inside a table. + echo(''); + echo(' + + + +
    All Clients + '); + echo('
    '); + + // Display the clients + echo(''); + echo(''); + foreach ($clients as $client) + { + // If the client is active highlight + $client_active = dbFetchRows("SELECT active FROM aironet_clients WHERE client_ip='".$client['client_ip']."' AND active='y'"); + if (empty($client_active)) + { + unset($active); + } + else + { + $active = 'class="clientconnected"'; + } + + $client_id = gethostbyaddr($client['client_ip']); + + $url = generate_url(array('page' => 'wifi_client', + 'client' => $client['client_ip'])); + $ap_device = device_by_id_cache($client['device_id']); + echo(' + + '); + } + echo('
    Client
    '.$client_id.'
    '); + + return; +} + +// If a client is specified then display all charts relating to that +// client, otherwise, show all charts assocaited with this +// basestation + +// If there is no device specified in the URL, generate an error. +if (empty($vars['client'])) +{ + display_all_clients(); +} +else +{ + display_client($vars['client']); +} + +?> diff --git a/includes/definitions/graphtypes.inc.php b/includes/definitions/graphtypes.inc.php index 0b4eec2..d9f9e7e 100644 --- a/includes/definitions/graphtypes.inc.php +++ b/includes/definitions/graphtypes.inc.php @@ -15,9 +15,13 @@ $config['graph_types']['port']['errors'] = array('name' => 'Errors', $config['graph_types']['port']['etherlike'] = array('name' => 'Ethernet Errors', 'descr' => "Detailed Errors/sec for Ethernet-like interfaces"); $config['graph_types']['port']['fdb_count'] = array('name' => 'FDB counts', 'descr' => "FDB count"); +// Charts by access point $config['graph_types']['device']['wifi_clients']['section'] = 'wireless'; $config['graph_types']['device']['wifi_clients']['order'] = '0'; -$config['graph_types']['device']['wifi_clients']['descr'] = 'Wireless Clients'; +$config['graph_types']['device']['wifi_clients']['descr'] = 'Wireless Client Count'; +$config['graph_types']['device']['wifi_client']['section'] = 'wireless'; +$config['graph_types']['device']['wifi_client']['order'] = '0'; +$config['graph_types']['device']['wifi_client']['descr'] = 'Wireless Client data'; // NetApp graphs $config['graph_types']['device']['netapp_ops'] = array('section' => 'netapp', 'descr' => 'NetApp Operations', 'order' => '0'); diff --git a/includes/polling/wifi.inc.php b/includes/polling/wifi.inc.php index 32c199a..d7d19d7 100644 --- a/includes/polling/wifi.inc.php +++ b/includes/polling/wifi.inc.php @@ -1,3 +1,14 @@ +/* +To create a mac lookup database exported from pfsense DHCP status create a table + +create table mac_ip_host (mac VARCHAR(18), ip VARCHAR(16), hostname VARCHAR(255)); + +Import the data + +GRANT FILE ON *.* TO 'observium'@'localhost' IDENTIFIED BY PASSWORD 'xxx'; +LOAD DATA INFILE '/tmp/macs.csv' INTO TABLE mac_ip_host FIELDS TERMINATED BY ','; + +*/ 'n'), + 'aironet_clients', + '`device_id` = ?', + array($device['device_id'])); + + // Get the AP wireless stats + + $aironet_oids = array('cDot11ClientIpAddress', 'cDot11ClientSignalStrength','cDot11ClientSigQuality'); + foreach ($aironet_oids as $oid) + { + $aironet_stats = snmpwalk_cache_oid($device, $oid, $aironet_stats, "CISCO-DOT11-ASSOCIATION-MIB"); + } + + // This info need to be stuck in the model + foreach ($aironet_stats as $index => $stats) + { + $hex_ip = $stats['cDot11ClientIpAddress']; + if (strcmp($hex_ip, "00 00 00 00") == 0) + { + continue; + } + + // Extract the radio index/SSID + $keys = explode(".", $index); + $radio = $keys[0]; + $ssid = $keys[1]; + + $client_ip = hexdec(substr($hex_ip, 0, 2)) . "." . + hexdec(substr($hex_ip, 3, 2)) . "." . + hexdec(substr($hex_ip, 6, 2)) . "." . + hexdec(substr($hex_ip, 9, 2)); + + echo($client_ip . " " . $stats['cDot11ClientSignalStrength'] . "dBm " . $stats['cDot11ClientSigQuality'] . "dBm\n"); + + // Determine the RRD filename + $wificlientsrrd = $config['rrd_dir'] . "/" . $device['hostname'] . "/" . safename("wificlient-" . $client_ip . ".rrd"); + + // Create the rrd file if this is a new client and add a row the the + // airport_clients SQL table + if (!is_file($wificlientsrrd)) + { + rrdtool_create($wificlientsrrd," \ + DS:Signal2_4GHz:GAUGE:450:-100:0 \ + DS:Quality2_4GHz:GAUGE:450:0:100 \ + DS:Signal5GHz:GAUGE:450:-100:0 \ + DS:Quality5GHz:GAUGE:450:0:100"); + + // mysql: create table aironet_clients (device_id SMALLINT, client_ip VARCHAR(18), active CHAR, signal_db SMALLINT, quality_db SMALLINT, radio SMALLINT, ssid VARCHAR(32)); + dbInsert(array('device_id' => $device['device_id'], + 'client_ip' => $client_ip, + 'active' => 'y', + 'radio' => $radio, + 'ssid' => $ssid, + 'signal_db' => $stats['cDot11ClientSignalStrength'], + 'quality_db' => $stats['cDot11ClientSigQuality']), + 'aironet_clients'); + } + + // Mark the connection as active for the client connection to this + // basestation and update the stats + dbUpdate(array('active' => 'y', + 'radio' => $radio, + 'ssid' => $ssid, + 'signal_db' => $stats['cDot11ClientSignalStrength'], + 'quality_db' => $stats['cDot11ClientSigQuality']), + 'aironet_clients', + '`device_id` = ? AND `client_ip` = ?', + array($device['device_id'], $client_ip)); + + // Update the rrd file + $strength1 = ""; + $quality1 = ""; + $strength2 = ""; + $quality2 = ""; + if ($radio == 1) + { + $strength1 = $stats['cDot11ClientSignalStrength']; + $quality1 = $stats['cDot11ClientSigQuality']; + $strength2 = "U"; + $quality2 = "U"; + } + else if ($radio == 2) + { + $strength1 = "U"; + $quality1 = "U"; + $strength2 = $stats['cDot11ClientSignalStrength']; + $quality2 = $stats['cDot11ClientSigQuality']; + } + + $rrd_update = array ($strength1, $quality1, + $strength2, $quality2); + + rrdtool_update("$wificlientsrrd", $rrd_update); + } + + // Mark that this basestation has connections + $graphs['wifi_client'] = TRUE; } # MikroTik RouterOS @@ -73,7 +185,7 @@ if ($device['type'] == 'network' || $device['type'] == 'firewall' || $device['ty } ///# RRD Filling Code - if (isset($wificlients1) && $wificlients1 != "") + if (isset($wificlients1)) { $wificlientsrrd = $config['rrd_dir'] . "/" . $device['hostname'] . "/" . safename("wificlients-radio1.rrd");