class Arpdb::Arp

Class to fetch ARP tables from Juniper firewalls, maintain them in memory and perform search operations on the cached data.

Attributes

db[RW]
snmp_transports[RW]

Public Class Methods

new(snmp_transports) click to toggle source

Oh gimme my syringe, I want to do some dependency injection! On a more serious note: snmp_transports is expected to be either Arpdb::SNMPTransport or array of those. This way we can easily pass mocked SNMPTransport here for off-the-hook testing.

# File lib/arpdb/arp.rb, line 16
def initialize(snmp_transports)
  @snmp_transports = Array(snmp_transports)
  @db = Array.new
end

Public Instance Methods

ip_to_mac(ip) click to toggle source
# File lib/arpdb/arp.rb, line 53
def ip_to_mac(ip)
  dblookup(:ip, ip, :mac)
end
locate_ip(ip) click to toggle source
# File lib/arpdb/arp.rb, line 61
def locate_ip(ip)
  dblookup(:ip, ip, :location)
end
locate_mac(mac) click to toggle source
# File lib/arpdb/arp.rb, line 57
def locate_mac(mac)
  dblookup(:mac, mac_flatten(mac), :location)
end
mac_to_ip(mac) click to toggle source
# File lib/arpdb/arp.rb, line 49
def mac_to_ip(mac)
  dblookup(:mac, mac_flatten(mac), :ip)
end
rescan() click to toggle source
# File lib/arpdb/arp.rb, line 21
def rescan
  scan
end
scan() click to toggle source
# File lib/arpdb/arp.rb, line 25
def scan
  sys_location = '1.3.6.1.2.1.1.6.0'
  ip_net_to_media_phys_address = '1.3.6.1.2.1.4.22.1.2'
  ip_net_to_media_net_address = '1.3.6.1.2.1.4.22.1.3'
  @db = Array.new
  handle_exceptions do
    dirty = false
    snmp_transports.each do |st|
      begin
        st.walk([ip_net_to_media_phys_address, ip_net_to_media_net_address]).each do |mac, ip|
          @db << {mac: mac, ip: ip, host: st.host, location: st.get(sys_location)}
        end
      rescue => e
        dirty = true
        msgs ||= []
        msgs << "SNMPTransport error while scanning #{st.host}; moving to next host (if any)"
        next
      end
    end
    raise msgs.join("; ") if dirty
  end
  self
end

Private Instance Methods

dblookup(key, match_value, return_key) click to toggle source
# File lib/arpdb/arp.rb, line 75
def dblookup(key, match_value, return_key)
  return '' if match_value.nil?

  line = db.find { |line| line[key].eql?(match_value) }
  line ? line[return_key] : ''
end
handle_exceptions() { || ... } click to toggle source
# File lib/arpdb/arp.rb, line 67
def handle_exceptions
  begin
    yield
  rescue => e
    raise ArpdbError, "Exception in Arpdb::Arp: #{e}"
  end
end
mac_flatten(mac) click to toggle source
# File lib/arpdb/arp.rb, line 82
def mac_flatten(mac)
  return '' if mac.nil?
  mac.downcase.gsub(':', '')
end