2018-07-11 18:58:23 +02:00
#!/usr/bin/env ruby
2011-01-17 01:51:57 +01:00
#
# Munin plugin for the D-link DIR-655 router
#
# This plugin can graph # of wifi clients, # of DHCP clients, collisions & errors for all network interfaces, dropped packets for all interfaces, and both transmit and receive rates for all interfaces of the router.
#
# Author: David Reitz
#
# 1. Copy script to a Linux server on your network.
# 2. Create symlink. (ln -s /path/to/dlink_dir655 /etc/munin/plugins/dlink_dir655)
# 3. Edit plugin configuration for this script (vi /etc/munin/plugin-conf.d/munin-node) and add:
# [dlink_dir655]
# host_name dir655
# env.router_password password
# env.router_ip_address 10.0.0.1
# 4. Edit munin configuration to point to itself to gather the data from your router (vi /etc/munin/munin-conf.d/munin) and add:
# [dir655]
# address 127.0.0.1
# use_node_name no
# 5. Modify the 'password' and 'router_path' variables below to reflect the correct password for the 'User' user on your D-link DIR-655 router and to reflect the correct IP address of your router (this *MUST* be on your local subnet/LAN).
#
# NOTICE 1: This is the first Ruby script I've written (as well as being my first Munin plugin), so I consider this a bit of a hack. Just letting you know ahead of time. :)
#
# NOTICE 2: I provide this script *as-is*. Use at your own risk! I thought other people may find this script useful/interesting but have no plans to support it for anyone else.
#
# Many thanks go to Clarke Brunsdon for his code listed at http://clarkebrunsdon.com/2010/12/the-dlink-dir-655-hash-changes/!!! This really helped me out!
#
# Original Implementation: 13 Jan 2011
gem 'mechanize'
require 'mechanize'
require 'digest/md5'
require 'nokogiri'
def output
nics = Hash.new
nics["LAN"] = Hash.new
nics["WAN"] = Hash.new
nics["WLAN"] = Hash.new
password = ENV['router_password'] || ""
router_path = ENV['router_ip_address'] || "10.0.0.1"
router_path = "http://" + router_path
agent = Mechanize.new
x = agent.get(router_path)
salt = x.body.match(/salt = "(.*)"/)[1]
2018-08-02 02:03:42 +02:00
2011-01-17 01:51:57 +01:00
# pad the pasword to length 16
pad_size = (16 - password.length)
padded_password = password + "\x01" * pad_size
2018-08-02 02:03:42 +02:00
2011-01-17 01:51:57 +01:00
# pad it the rest of the way, length 64 for user
salted_password = salt + padded_password + ("\x01" * (63 - salt.length - padded_password.length)) + "U"
login_hash = salt + Digest::MD5.hexdigest(salted_password)
2018-08-02 02:03:42 +02:00
2011-01-17 01:51:57 +01:00
# authenticate against the router using the hash that we just built
login_path = "#{router_path}/post_login.xml?hash=#{login_hash}"
x = agent.get(login_path)
# grab the statistics for all interfaces and parse it into a usable form
clients_xml = agent.get("#{router_path}/interface_stats.xml").body
doc = Nokogiri::XML(clients_xml.to_s)
doc.xpath('//interface').each do |interface|
children = interface.children
name = children.search('name')[0].text
nics[name]["packets_sent"] = children.search('packets_sent')[0].text
nics[name]["packets_received"] = children.search('packets_received')[0].text
nics[name]["tx_dropped"] = children.search('tx_dropped')[0].text
begin
nics[name]["tx_collisions"] = children.search('tx_collisions')[0].text
rescue Exception
nics[name]["tx_collisions"] = "0"
end
nics[name]["rx_dropped"] = children.search('rx_dropped')[0].text
nics[name]["rx_errors"] = children.search('rx_errors')[0].text
end
# get wifi associations and print out info for munin graph
puts "multigraph clients"
clients_xml = agent.get("#{router_path}/wifi_assoc.xml").body
j = 0
doc = Nokogiri::XML(clients_xml.to_s)
doc.xpath('//assoc').each do |assoc|
j+=1
end
puts "wifi_assoc.value " + j.to_s
# get dhcp clients and print out info for munin graph
clients_xml = agent.get("#{router_path}/dhcp_clients.xml").body
j = 0
doc = Nokogiri::XML(clients_xml.to_s)
doc.xpath('//client').each do |client|
j+=1
end
puts "dhcp_clients.value " + j.to_s
2011-02-09 03:12:28 +01:00
puts "multigraph uptime"
# get uptime of connection
clients_xml = agent.get("#{router_path}/wan_connection_status.xml").body
doc = Nokogiri::XML(clients_xml.to_s)
uptime = doc.children.search('wan_interface_up_time_0')[0].text
puts "uptime.value " + sprintf( "%.2f", (Float(uptime)/86400) )
2011-01-17 01:51:57 +01:00
# graph overall interface packets transferred per interval
puts "multigraph if_packets"
for i in [ "LAN", "WAN", "WLAN" ] do
puts "#{i}_recv.value " + nics[i]["packets_received"]
puts "#{i}_send.value " + nics[i]["packets_sent"]
end
# graph overall interface dropped packets per interval
puts "multigraph if_drop"
for i in [ "LAN", "WAN", "WLAN" ] do
puts "#{i}_recv.value " + nics[i]["rx_dropped"]
puts "#{i}_send.value " + nics[i]["tx_dropped"]
end
# graph overall interface collisions & errors per interval
puts "multigraph if_collerr"
for i in [ "LAN", "WAN", "WLAN" ] do
puts "#{i}_coll.value " + nics[i]["tx_collisions"]
puts "#{i}_err.value " + nics[i]["rx_errors"]
end
2018-08-02 02:03:42 +02:00
2011-01-17 01:51:57 +01:00
# graph stats for each interface
for i in [ "LAN", "WAN", "WLAN" ] do
puts "multigraph if_packets.#{i}"
puts "send.value " + nics[i]["packets_sent"]
puts "recv.value " + nics[i]["packets_received"]
puts "multigraph if_drop.#{i}"
puts "send.value " + nics[i]["tx_dropped"]
puts "recv.value " + nics[i]["rx_dropped"]
puts "multigraph if_collerr.#{i}"
puts "coll.value " + nics[i]["tx_collisions"]
puts "err.value " + nics[i]["rx_errors"]
end
end
def config
# build the configuration for graphs
puts "multigraph if_packets"
puts 'graph_title D-Link DIR-655 interface traffic'
puts 'graph_category network'
puts 'graph_order LAN_recv LAN_send WAN_recv WAN_send WLAN_recv WLAN_send'
puts 'graph_vlabel packets in (-) / out (+) per ${graph_period}'
for i in [ "LAN", "WAN", "WLAN" ] do
2011-02-09 03:12:28 +01:00
puts "#{i}_recv.type DERIVE"
2011-01-17 01:51:57 +01:00
puts "#{i}_recv.graph no"
puts "#{i}_recv.min 0"
puts "#{i}_send.label #{i}"
2011-02-09 03:12:28 +01:00
puts "#{i}_send.type DERIVE"
2011-01-17 01:51:57 +01:00
puts "#{i}_send.negative #{i}_recv"
puts "#{i}_send.min 0"
end
puts "multigraph if_drop"
puts 'graph_title D-Link DIR-655 interface drops'
puts 'graph_category network'
puts 'graph_order LAN_recv LAN_send WAN_recv WAN_send WLAN_recv WLAN_send'
puts 'graph_vlabel packets / ${graph_period}'
for i in [ "LAN", "WAN", "WLAN" ] do
2011-02-09 03:12:28 +01:00
puts "#{i}_recv.type DERIVE"
2011-01-17 01:51:57 +01:00
puts "#{i}_recv.graph no"
puts "#{i}_recv.min 0"
puts "#{i}_send.label #{i}"
2011-02-09 03:12:28 +01:00
puts "#{i}_send.type DERIVE"
2011-01-17 01:51:57 +01:00
puts "#{i}_send.negative #{i}_recv"
puts "#{i}_send.min 0"
end
puts "multigraph if_collerr"
puts 'graph_title D-Link DIR-655 interface collisions & errors'
puts 'graph_category network'
puts 'graph_order LAN_coll LAN_err WAN_coll WAN_err WLAN_coll WLAN_coll'
puts 'graph_vlabel packets / ${graph_period}'
for i in [ "LAN", "WAN", "WLAN" ] do
puts "#{i}_coll.label #{i} collisions"
2011-02-09 03:12:28 +01:00
puts "#{i}_coll.type DERIVE"
2011-01-17 01:51:57 +01:00
puts "#{i}_coll.min 0"
puts "#{i}_err.label #{i} errors"
2011-02-09 03:12:28 +01:00
puts "#{i}_err.type DERIVE"
2011-01-17 01:51:57 +01:00
puts "#{i}_err.min 0"
end
puts "multigraph clients"
puts "graph_title D-Link DIR-655 client information"
2011-02-09 03:12:28 +01:00
puts "graph_category system"
2011-01-17 01:51:57 +01:00
puts "graph_order dhcp_clients wifi_assoc"
puts "graph_vlabel number of clients"
puts "dhcp_clients.label DHCP clients"
puts "dhcp_clients.type GAUGE"
puts "dhcp_clients.min 0"
puts "wifi_assoc.label wifi clients"
puts "wifi_assoc.type GAUGE"
puts "wifi_assoc.min 0"
2011-02-09 03:12:28 +01:00
puts "multigraph uptime"
puts "graph_title Uptime"
puts 'graph_vlabel uptime in days'
puts 'graph_category system'
puts 'uptime.label uptime'
puts 'uptime.draw AREA'
2011-01-17 01:51:57 +01:00
for i in [ "LAN", "WAN", "WLAN" ] do
puts "multigraph if_packets.#{i}"
puts "graph_title D-Link DIR-655 #{i} traffic"
puts 'graph_category network'
puts 'graph_order recv send'
puts 'graph_vlabel packets in (-) / out (+) per ${graph_period}'
puts 'recv.label received'
2011-02-09 03:12:28 +01:00
puts 'recv.type DERIVE'
2011-01-17 01:51:57 +01:00
puts 'recv.graph no'
puts 'recv.min 0'
puts 'send.label packets/sec'
2011-02-09 03:12:28 +01:00
puts 'send.type DERIVE'
2011-01-17 01:51:57 +01:00
puts 'send.negative recv'
puts 'send.min 0'
2018-08-02 02:03:42 +02:00
2011-01-17 01:51:57 +01:00
puts "multigraph if_drop.#{i}"
puts "graph_title D-Link DIR-655 #{i} drops"
puts 'graph_category network'
puts 'graph_order recv send'
puts 'graph_vlabel packets / ${graph_period}'
puts 'recv.label RX packets dropped'
2011-02-09 03:12:28 +01:00
puts 'recv.type DERIVE'
2011-01-17 01:51:57 +01:00
puts 'recv.graph no'
puts 'recv.min 0'
puts 'send.label TX packets dropped'
2011-02-09 03:12:28 +01:00
puts 'send.type DERIVE'
2011-01-17 01:51:57 +01:00
puts 'send.negative recv'
puts 'send.min 0'
2018-08-02 02:03:42 +02:00
2011-01-17 01:51:57 +01:00
puts "multigraph if_collerr.#{i}"
puts "graph_title D-Link DIR-655 #{i} collisions & errors"
puts 'graph_category network'
puts 'graph_order coll err'
puts 'graph_vlabel packets / ${graph_period}'
puts 'coll.label collisions'
2011-02-09 03:12:28 +01:00
puts 'coll.type DERIVE'
2011-01-17 01:51:57 +01:00
puts 'coll.min 0'
puts 'err.label errors'
2011-02-09 03:12:28 +01:00
puts 'err.type DERIVE'
2011-01-17 01:51:57 +01:00
puts 'err.min 0'
end
end
# main
if ARGV.length == 1 and ARGV[0] == 'config'
config()
else
output()
end