I’m a novice Ruby programmer and I’ve come up against a problem which I
really have no idea as to how to fix. I’m making a small Ruby/RoR web
application to poll and display information from SNMP devices. The
problem I’m having is trying to poll an IP range for SNMP enabled
devices. I hacked together a small method to do this using the
SNMP Scanner gem/command line app as a basis
(http://snmpscan.rubyforge.org). I just modified it by throwing it into
a method and have
it return an array of “live” IP addresses.
In application.rb
class IPAddr
The broadcast method calculate the broadcast
address of the range (if any)
def broadcast
return @addr + (IPAddr::IN4MASK - @mask_addr)
end
# The each_address method iterates over each address
# of the ip range
def each_address
(@addr…broadcast).each do |addr|
yield _to_string(addr)
end
end
end
[/code]
#In network_controller.rb
def poll(inc_ip)
# Default Settings
timeout = 200
mib = "sysDescr.0"
protocol = "2c"
comunity = "public"
verbose = false
args = [timeout,mib,protocol,comunity]
live = []
iprange = IPAddr.new(inc_ip)
threads = []
iprange.each_address do |ip|
begin
threads << Thread.new(ip,args) do |ip,args|
timeout,mib,protocol,comunity = args
begin
SNMP::Manager.open(:Host => ip,
:Community => comunity,
:Port => 161,
:Timeout => (timeout/1000.0)) do |man|
res = man.get([mib])
answer = res.varbind_list[0].value
live << "#{ip}"
print "#{ip}:\t#{answer}\n"
end
end
end
rescue
next
end
end
ThreadsWait.all_waits(threads)
return live
end
To test, I just an action to poll a range (10.1.1.1-10.1.1.254) and
flash the first result to me:
#In network_controller.rb
def live_devices
live = Array.new(poll("10.1.1.1/24"))
flash[:notice] = live[0]
redirect_to :action => 'list'
end
This works fine and reveals the IP addresses of two SNMP devices on my
network just fine. However, if I try to poll 192.168.1.1/24, the
application hangs and seems to spawn hundreds of threads, most of which
never complete. In the command line window I can see it returning the
first and only SNMP device within that range, the router at 192.168.1.1.
My knowledge of CIDR notation is cursory but 192.168.1.1/24 should scan
between 192.168.1.1 and 192.168.1.254 unless I’m mistaken. I’m stumped
as to what the problem is. Either there’s a serious problem with the
threading somewhere or something else. Another thing I noted is that
using the SNMP scanner gem from the command line to scan a single IP
address works fine, but using the code above to scan single IP returns
nothing.
This is all very confusing
Edit: I don’t think I’m initialising the IPAddr object I want
correctly as calling “iprange = IPTest.new(inc_ip)” after renaming the
IPAddr class in application.rb to IPTest throws an error. I think this
is where my problem lies.
I’ve moved the code from application.rb to iptest.rb in /lib and use
require ‘iptest’ in environment.rb but now calling the live_devices
action just yields a “wrong number of arguments (1 for 0)” error.
Perhaps it’s not loaded correctly?