class SNMP::TrapListener

SNMP Trap Listener

Listens to a socket and processes received traps and informs in a separate thread.

Example

require 'snmp'

m = SNMP::TrapListener.new(:Port => 1062, :Community => 'public') do |manager|
  manager.on_trap_default { |trap| p trap }
end
m.join

Constants

NULL_HANDLER

Attributes

config[R]

Retrieves the current configuration of this TrapListener.

Public Class Methods

new(options={}, &block) click to toggle source

Start a trap handler thread. If a block is provided then the block is executed before trap handling begins. This block is typically used to define the trap handler blocks.

The trap handler blocks execute in the context of the trap handler thread.

The most specific trap handler is executed when a trap arrives. Only one handler is executed. The handlers are checked in the following order:

  1. handler for a specific OID

  2. handler for a specific SNMP version

  3. default handler

The default for the :community option is 'nil' allows traps with any community to be accepted. To only accept traps from a specific community, the community may also be set to a string (e.g. 'public') or a list of strings (e.g. ['public', 'my_private_community'] ).

# File lib/snmp/manager.rb, line 603
def initialize(options={}, &block)
  config = Config.new(options)
  @transport = config.create_transport
  @community = config.community
  @max_bytes = config.max_recv_bytes
  @mib = MIB.new
  load_modules(config.mib_modules, config.mib_dir)
  @config = config.applied_config

  @handler_init = block
  @oid_handler = {}
  @v1_handler = nil
  @v2c_handler = nil
  @default_handler = nil
  @lock = Mutex.new
  @handler_thread = Thread.new(self) { |m| process_traps(m) }
end

Public Instance Methods

exit() click to toggle source

Stops the trap handler thread and releases the socket.

See also Thread#exit.

# File lib/snmp/manager.rb, line 675
def exit
  @handler_thread.exit
  @transport.close
end
Also aliased as: kill, terminate
join() click to toggle source

Joins the current thread to the trap handler thread.

See also Thread#join.

# File lib/snmp/manager.rb, line 666
def join
  @handler_thread.join
end
kill()
Alias for: exit
on_trap(object_id, &block) click to toggle source

Define a trap handler block for a specific trap ObjectId. This handler only applies to SNMPv2 traps. Note that symbolic OIDs are not supported by this method (like in the SNMP.Manager class).

# File lib/snmp/manager.rb, line 636
def on_trap(object_id, &block)
  raise ArgumentError, "a block must be provided" unless block
  @lock.synchronize { @oid_handler[ObjectId.new(object_id)] = block }
end
on_trap_default(&block) click to toggle source

Define the default trap handler. The default trap handler block is executed only if no other block is applicable. This handler should expect to receive both SNMPv1_Trap and SNMPv2_Trap objects.

# File lib/snmp/manager.rb, line 626
def on_trap_default(&block)
  raise ArgumentError, "a block must be provided" unless block
  @lock.synchronize { @default_handler = block }
end
on_trap_v1(&block) click to toggle source

Define a trap handler block for all SNMPv1 traps. The trap yielded to the block will always be an SNMPv1_Trap.

# File lib/snmp/manager.rb, line 645
def on_trap_v1(&block)
  raise ArgumentError, "a block must be provided" unless block
  @lock.synchronize { @v1_handler = block }
end
on_trap_v2c(&block) click to toggle source

Define a trap handler block for all SNMPv2c traps. The trap yielded to the block will always be an SNMPv2_Trap. Note that InformRequest is a subclass of SNMPv2_Trap, so inform PDUs are also received by this handler.

# File lib/snmp/manager.rb, line 656
def on_trap_v2c(&block)
  raise ArgumentError, "a block must be provided" unless block
  @lock.synchronize { @v2c_handler = block }
end
terminate()
Alias for: exit

Private Instance Methods

community_allowed?(msg_community) click to toggle source
# File lib/snmp/manager.rb, line 712
def community_allowed?(msg_community)
  @community.nil? || @community == msg_community || !(Array(@community) & Array(msg_community)).empty?
end
load_modules(module_list, mib_dir) click to toggle source
# File lib/snmp/manager.rb, line 685
def load_modules(module_list, mib_dir)
  module_list.each { |m| @mib.load_module(m, mib_dir) }
end
process_traps(trap_listener) click to toggle source
# File lib/snmp/manager.rb, line 689
def process_traps(trap_listener)
  @handler_init.call(trap_listener) if @handler_init
  loop do
    data, source_ip, source_port = @transport.recvfrom(@max_bytes)
    begin
      message = Message.decode(data, @mib)
      if community_allowed? message.community
        trap = message.pdu
        if trap.kind_of?(InformRequest)
          @transport.send(message.response.encode, source_ip, source_port)
        end
        trap.source_ip = source_ip
        select_handler(trap).call(trap)
      end
    rescue => e
      puts "Error handling trap: #{e}"
      puts e.backtrace.join("\n")
      puts "Received data:"
      p data
    end
  end
end
select_handler(trap) click to toggle source
# File lib/snmp/manager.rb, line 716
def select_handler(trap)
  @lock.synchronize do
    if trap.kind_of?(SNMPv2_Trap)
      oid = trap.trap_oid
      if @oid_handler[oid]
        return @oid_handler[oid]
      elsif @v2c_handler
        return @v2c_handler
      elsif @default_handler
        return @default_handler
      else
        return NULL_HANDLER
      end
    elsif trap.kind_of?(SNMPv1_Trap)
      if @v1_handler
        return @v1_handler
      elsif @default_handler
        return @default_handler
      else
        return NULL_HANDLER
      end
    else
      return NULL_HANDLER
    end
  end
end