diff --git a/callback.php b/callback.php new file mode 100644 index 000000000..bbfe57260 --- /dev/null +++ b/callback.php @@ -0,0 +1,101 @@ + + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. Please see LICENSE.txt at the top level of + * the source code distribution for details. + */ + +$enabled = dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'enabled'"); +if ($enabled == 1) { + + if (dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'uuid'") == '') { + dbInsert(array('name'=>'uuid','value'=>guidv4(openssl_random_pseudo_bytes(16))),'callback'); + } + $uuid = dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'uuid'"); + + $queries = array( + 'alert_rules'=>'SELECT COUNT(`severity`) AS `total`,`severity` FROM `alert_rules` WHERE `disabled`=0 GROUP BY `severity`', + 'alert_templates'=>'SELECT COUNT(`id`) AS `total` FROM `alert_templates`', + 'api_tokens'=>'SELECT COUNT(`id`) AS `total` FROM `api_tokens` WHERE `disabled`=0', + 'applications'=>'SELECT COUNT(`app_type`) AS `total`,`app_type` FROM `applications` GROUP BY `app_type`', + 'bgppeer_state'=>'SELECT COUNT(`bgpPeerState`) AS `total`,`bgpPeerState` FROM `bgpPeers` GROUP BY `bgpPeerState`', + 'bgppeer_status'=>'SELECT COUNT(`bgpPeerAdminStatus`) AS `total`,`bgpPeerAdminStatus` FROM `bgpPeers` GROUP BY `bgpPeerAdminStatus`', + 'bills'=>'SELECT COUNT(`bill_type`) AS `total`,`bill_type` FROM `bills` GROUP BY `bill_type`', + 'cef'=>'SELECT COUNT(`device_id`) AS `total` FROM `cef_switching`', + 'cisco_asa'=>'SELECT COUNT(`oid`) AS `total`,`oid` FROM `ciscoASA` WHERE `disabled` = 0 GROUP BY `oid`', + 'mempool'=>'SELECT COUNT(`cmpName`) AS `total`,`cmpName` FROM `cmpMemPool` GROUP BY `cmpName`', + 'current'=>'SELECT COUNT(`current_type`) AS `total`,`current_type` FROM `current` GROUP BY `current_type`', + 'dbschema'=>'SELECT COUNT(`version`) AS `total`, `version` FROM `dbSchema`', + 'snmp_version'=>'SELECT COUNT(`snmpver`) AS `total`,`snmpver` FROM `devices` GROUP BY `snmpver`', + 'os'=>'SELECT COUNT(`os`) AS `total`,`os` FROM `devices` GROUP BY `os`', + 'type'=>'SELECT COUNT(`type`) AS `total`,`type` FROM `devices` GROUP BY `type`', + 'full_type'=>'SELECT COUNT(`device_id`) AS `total`, CONCAT_WS(', ', `os`,`hardware`,`type`) FROM `devices` GROUP BY `os`,`hardware`,`type`', + 'ipsec'=>'SELECT COUNT(`device_id`) AS `total` FROM `ipsec_tunnels`', + 'ipv4_addresses'=>'SELECT COUNT(`ipv4_address_id`) AS `total` FROM `ipv4_addresses`', + 'ipv4_macaddress'=>'SELECT COUNT(`port_id`) AS `total` FROM ipv4_mac', + 'ipv4_networks'=>'SELECT COUNT(`ipv4_network_id`) AS `total` FROM ipv4_networks', + 'ipv6_addresses'=>'SELECT COUNT(`ipv6_address_id`) AS `total` FROM `ipv6_addresses`', + 'ipv6_networks'=>'SELECT COUNT(`ipv6_network_id`) AS `total` FROM `ipv6_networks`', + 'xdp'=>'SELECT COUNT(`id`) AS `total`,`protocol` FROM `links` GROUP BY `protocol`', + 'ospf'=>'SELECT COUNT(`device_id`) AS `total`,`ospfVersionNumber` FROM `ospf_instances` GROUP BY `ospfVersionNumber`', + 'ospf_links'=>'SELECT COUNT(`device_id`) AS `total`,`ospfIfType` FROM `ospf_ports` GROUP BY `ospfIfType`', + 'arch'=>'SELECT COUNT(`pkg_id`) AS `total`,`arch` FROM `packages` GROUP BY `arch`', + 'pollers'=>'SELECT COUNT(`id`) AS `total` FROM `pollers`', + 'port_type'=>'SELECT COUNT(`port_id`) AS `total`,`ifType` FROM `ports` GROUP BY `ifType`', + 'port_ifspeed'=>'SELECT COUNT(`ifSpeed`) AS `total`,ROUND(`ifSpeed`/1000/1000) FROM `ports` GROUP BY `ifSpeed`', + 'port_vlans'=>'SELECT COUNT(`device_id`) AS `total`,`state` FROM `ports_vlans` GROUP BY `state`', + 'processes'=>'SELECT COUNT(`device_id`) AS `total` FROM `processes`', + 'processors'=>'SELECT COUNT(`processor_id`) AS `total`,`processor_type` FROM `processors` GROUP BY `processor_type`', + 'pseudowires'=>'SELECT COUNT(`pseudowire_id`) AS `total` FROM `pseudowires`', + 'sensors'=>'SELECT COUNT(`sensor_id`) AS `total`,`sensor_class` FROM `sensors` GROUP BY `sensor_class`', + 'storage'=>'SELECT COUNT(`storage_id`) AS `total`,`storage_type` FROM `storage` GROUP BY `storage_type`', + 'toner'=>'SELECT COUNT(`toner_id`) AS `total`,`toner_type` FROM `toner` GROUP BY `toner_type`', + 'vlans'=>'SELECT COUNT(`vlan_id`) AS `total`,`vlan_type` FROM `vlans` GROUP BY `vlan_type`', + 'vminfo'=>'SELECT COUNT(`id`) AS `total`,`vm_type` FROM `vminfo` GROUP BY `vm_type`', + 'vmware'=>'SELECT COUNT(`id`) AS `total` FROM `vmware_vminfo`', + 'vrfs'=>'SELECT COUNT(`vrf_id`) AS `total` FROM `vrfs`'); + + + foreach ($queries as $name => $query) { + $data = dbFetchRows($query); + $response[$name] = $data; + } + $output = array('uuid'=>$uuid,'data'=>$response); + $data = json_encode($output); + $submit = array('data'=>$data); + + $fields = ''; + foreach($submit as $key => $value) { + $fields .= $key . '=' . $value . '&'; + } + rtrim($fields, '&'); + + $post = curl_init(); + curl_setopt($post, CURLOPT_URL, $config['callback_post']); + curl_setopt($post, CURLOPT_POST, count($submit)); + curl_setopt($post, CURLOPT_POSTFIELDS, $fields); + curl_setopt($post, CURLOPT_RETURNTRANSFER, 1); + $result = curl_exec($post); +} elseif ($enabled == 2) { + + $uuid = dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'uuid'"); + $fields = "uuid=$uuid"; + + $clear = curl_init(); + curl_setopt($clear, CURLOPT_URL, $config['callback_clear']); + curl_setopt($clear, CURLOPT_POST, count($clear)); + curl_setopt($clear, CURLOPT_POSTFIELDS, $fields); + curl_setopt($clear, CURLOPT_RETURNTRANSFER, 1); + $result = curl_exec($clear); + dbDelete('callback','`name`="uuid"',array()); + dbUpdate(array('value' => '0'), 'callback', '`name` = "enabled"', array()); +} + +?> diff --git a/daily.php b/daily.php index 38ac1584e..03176a47d 100644 --- a/daily.php +++ b/daily.php @@ -55,5 +55,8 @@ if ($options['f'] === 'perf_times') { } } } +if ($options['f'] === 'callback') { + require_once "callback.php"; +} ?> diff --git a/daily.sh b/daily.sh index ca8c87077..4168d7344 100644 --- a/daily.sh +++ b/daily.sh @@ -11,3 +11,4 @@ php daily.php -f syslog php daily.php -f eventlog php daily.php -f authlog php daily.php -f perf_times +php daily.php -f callback diff --git a/doc/General/Callback-Stats-and-Privacy.md b/doc/General/Callback-Stats-and-Privacy.md new file mode 100644 index 000000000..e0d32c7a7 --- /dev/null +++ b/doc/General/Callback-Stats-and-Privacy.md @@ -0,0 +1,32 @@ +## Stats data and your privacy ## + +This document has been put together to explain what LibreNMS does when it calls back home to report some anonymous statistics. + +Let's start off by saying, all of the code that processes the data and submits it is included in the standard LibreNMS branch you've installed, the code that accepts this data and in turn generates some pretty graphs is all open source and available on Git Hub. Please feel free to review the code, comment on it and suggest changes / improvements. Also, don't forget - by default installations DO NOT call back home, you need to opt into this. + +Above all we respect users privacy which is why this system has been designed like it has. + +Now onto the bit you're interested in, what is submitted and what we do with that data. + +#### What is submitted #### +- All data is anonymous. +- Generic statistics are taken from the database, these include things like device total, type and os, port types, speeds and total, total bgp peers. Take a look at the code for full details. +- A random UUID is generated on your own install. +- That's it! +- Your IP isn't logged, even via our web service accepting the data. We don't need to know who you are so don't ask. + +#### What we do with the data #### +- We store it, not for long - 3 months at the moment although this could change. +- We use it to generate pretty graphs for people to see. +- We use it to help prioritise issues and features that need to be worked on. + +#### Questions? #### +- Q. How often is data submitted? A. We submit the data once a day according to running daily.sh via cron. If you disable this then opting in will not have any affect. +- Q. Where can I see the data I submitted? A. You can't see the data raw, but we collate all of the data together and provide a dynamic site so you can see the results of all contributed stats [here](https://stats.librenms.org) +- Q. I want my data removed. A. That's easy, simply press 'Clear remote stats' in the About LibreNMS page of your control panel, the next time the call back script is run it will remove all the data we have. +- Q. I clicked the 'Clear remote stats' button by accident. A. No problem, before daily.sh runs again - just opt back in, all of your existing data will stay. + +Hopefully this answers the questions you might have on why and what we are doing here, if not, please pop into our irc channel or google mailing list and ask any questions you like. + +If you're happy with all of this - please consider switching the call back system on, you can do this within the About LibreNMS page within your control panel. In the Statistics section you will find a toggle switch to enable / disable the feature. If you've previously had it switched on and want to opt out and remove your data, click the 'Clear remote stats' button and on the next submission all the data you've sent us will be removed! + diff --git a/doc/Installation/Installation-(Debian-Ubuntu).md b/doc/Installation/Installation-(Debian-Ubuntu).md index d85aa6ff4..4df0bfee4 100644 --- a/doc/Installation/Installation-(Debian-Ubuntu).md +++ b/doc/Installation/Installation-(Debian-Ubuntu).md @@ -42,7 +42,7 @@ This host is where the web server and SNMP poller run. It could be the same mac Install the required software: - apt-get install libapache2-mod-php5 php5-cli php5-mysql php5-gd php5-snmp php-pear snmp graphviz php5-mcrypt php5-json apache2 fping imagemagick whois mtr-tiny nmap python-mysqldb snmpd mysql-client php-net-ipv4 php-net-ipv6 rrdtool git + apt-get install libapache2-mod-php5 php5-cli php5-mysql php5-gd php5-snmp php-pear php5-curl snmp graphviz php5-mcrypt php5-json apache2 fping imagemagick whois mtr-tiny nmap python-mysqldb snmpd mysql-client php-net-ipv4 php-net-ipv6 rrdtool git The packages listed above are an all-inclusive list of packages that were necessary on a clean install of Ubuntu 12.04/14.04. diff --git a/doc/Installation/Installation-(RHEL-CentOS).md b/doc/Installation/Installation-(RHEL-CentOS).md index 4dd28a6f8..e8a17014d 100644 --- a/doc/Installation/Installation-(RHEL-CentOS).md +++ b/doc/Installation/Installation-(RHEL-CentOS).md @@ -47,7 +47,7 @@ Install necessary software. The packages listed below are an all-inclusive list Note if not using HTTPd (Apache): RHEL requires `httpd` to be installed regardless of of `nginx`'s (or any other web-server's) presence. rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm - yum install php php-cli php-gd php-mysql php-snmp php-pear httpd net-snmp graphviz graphviz-php mysql ImageMagick jwhois nmap mtr rrdtool MySQL-python net-snmp-utils vixie-cron php-mcrypt fping git + yum install php php-cli php-gd php-mysql php-snmp php-pear php-curl httpd net-snmp graphviz graphviz-php mysql ImageMagick jwhois nmap mtr rrdtool MySQL-python net-snmp-utils vixie-cron php-mcrypt fping git pear install Net_IPv4-1.3.4 pear install Net_IPv6-1.2.2b2 diff --git a/doc/Installation/Installation-Lighttpd-(Debian-Ubuntu).md b/doc/Installation/Installation-Lighttpd-(Debian-Ubuntu).md index 0af3cc363..196654283 100644 --- a/doc/Installation/Installation-Lighttpd-(Debian-Ubuntu).md +++ b/doc/Installation/Installation-Lighttpd-(Debian-Ubuntu).md @@ -37,7 +37,7 @@ Change `127.0.0.1` to the IP address that your MySQL server should listen on. R Install necessary software. The packages listed below are an all-inclusive list of packages that were necessary on a clean install of Debian 7. - apt-get install lighttpd php5-cli php5-mysql php5-gd php5-snmp php5-cgi php-pear snmp graphviz mysql-server mysql-client rrdtool sendmail fping imagemagick whois mtr-tiny nmap ipmitool php5-mcrypt php5-json python-mysqldb snmpd php-net-ipv4 php-net-ipv6 rrdtool git + apt-get install lighttpd php5-cli php5-mysql php5-gd php5-snmp php5-cgi php-pear php5-curl snmp graphviz mysql-server mysql-client rrdtool sendmail fping imagemagick whois mtr-tiny nmap ipmitool php5-mcrypt php5-json python-mysqldb snmpd php-net-ipv4 php-net-ipv6 rrdtool git ### Cloning ### diff --git a/html/forms/callback-clear.inc.php b/html/forms/callback-clear.inc.php new file mode 100644 index 000000000..236c28c90 --- /dev/null +++ b/html/forms/callback-clear.inc.php @@ -0,0 +1,15 @@ + + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. Please see LICENSE.txt at the top level of + * the source code distribution for details. + */ + +dbUpdate(array('value' => '2'), 'callback', '`name` = "enabled"', array()); diff --git a/html/forms/callback-statistics.inc.php b/html/forms/callback-statistics.inc.php new file mode 100644 index 000000000..22f65e71d --- /dev/null +++ b/html/forms/callback-statistics.inc.php @@ -0,0 +1,25 @@ + + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. Please see LICENSE.txt at the top level of + * the source code distribution for details. + */ + +if ($_POST['state'] == 'true') { + $state = 1; +} elseif ($_POST['state'] == 'false') { + $state = 0; +} else { + $state = 0; +} + +if( dbUpdate(array('value' => $state), 'callback', '`name` = "enabled"', array()) == 0) { + dbInsert(array('value' => $state,'name' => 'enabled'), 'callback'); +} diff --git a/html/pages/about.inc.php b/html/pages/about.inc.php index 5bd15bbf4..994e436d3 100644 --- a/html/pages/about.inc.php +++ b/html/pages/about.inc.php @@ -67,10 +67,30 @@ $stat_pw = dbFetchCell("SELECT COUNT(pseudowire_id) FROM `pseudowires`"); $stat_vrf = dbFetchCell("SELECT COUNT(vrf_id) FROM `vrfs`"); $stat_vlans = dbFetchCell("SELECT COUNT(vlan_id) FROM `vlans`"); +$callback_status = dbFetchCell("SELECT `value` FROM `callback` WHERE `name` = 'enabled'"); +if ($callback_status == 1) { + $stats_checked = 'checked'; +} else { + $stats_checked = ''; +} +$callback = 'Opt in to send anonymous usage statistics to LibreNMS? '; + echo("
| $callback | +|||
| + | $stat_devices | $stat_ports | @@ -175,3 +195,35 @@ echo(" + + diff --git a/includes/defaults.inc.php b/includes/defaults.inc.php index 796c15a8d..7cee0e712 100644 --- a/includes/defaults.inc.php +++ b/includes/defaults.inc.php @@ -599,4 +599,8 @@ $config['distributed_poller_group'] = 0; $config['distributed_poller_memcached_host'] = 'example.net'; $config['distributed_poller_memcached_port'] = '11211'; +// Stats callback system +$config['callback_post'] = 'https://stats.librenms.org/log.php'; +$config['callback_clear'] = 'https://stats.librenms.org/clear.php'; + ?> diff --git a/includes/functions.php b/includes/functions.php index e3905e311..5865dc3a7 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -1129,4 +1129,15 @@ function convert_delay($delay) { return($delay_sec); } +function guidv4($data) { + // http://stackoverflow.com/questions/2040240/php-function-to-generate-v4-uuid#15875555 + // From: Jack http://stackoverflow.com/users/1338292/ja%CD%A2ck + assert(strlen($data) == 16); + + $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100 + $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10 + + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); +} + ?> diff --git a/sql-schema/046.sql b/sql-schema/046.sql new file mode 100644 index 000000000..9e7aaa2d7 --- /dev/null +++ b/sql-schema/046.sql @@ -0,0 +1 @@ +CREATE TABLE `librenms`.`callback` ( `callback_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `name` CHAR( 64 ) NOT NULL , `value` CHAR( 64 ) NOT NULL ) ENGINE = INNODB;