Skip to content

Complex example: SNMP

Sylvain Daubert edited this page Dec 22, 2017 · 2 revisions

Here is a complex Model example based on SNMP protocol:

# Class to handle SNMP VarBind
#  VarBind ::= SEQUENCE {
#                name  OBJECT IDENTIFIER,
#                value ANY     -- depends on name
#              }
class VarBind < RASN1::Model
  sequence :varbind,
           content: [objectid(:name),
                     any(:value)]
end

# Class to handle SNMP VariableBindingsList
#  VarBindList ::= SEQUENCE (SIZE (0..max-bindings)) OF VarBind
class VariableBindings < RASN1::Model
  sequence_of :bindings, VarBind
end

# Class to handle GetRequest PDU
#  GetRequest-PDU ::= [0] IMPLICIT PDU
#  
#  PDU ::= SEQUENCE {
#              request-id INTEGER (-214783648..214783647),
#              error-status
#                  INTEGER {
#                      noError(0),
#                      tooBig(1),
#                      noSuchName(2),
#                      badValue(3),
#                      readOnly(4),
#                      genErr(5),
#                      noAccess(6),
#                      wrongType(7),
#                      wrongLength(8),
#                      wrongEncoding(9),
#                      wrongValue(10),
#                      noCreation(11),
#                      inconsistentValue(12),
#                      resourceUnavailable(13),
#                      commitFailed(14),
#                      undoFailed(15),
#                      authorizationError(16),
#                      notWritable(17),
#                      inconsistentName(18)
#                  },
#              error-index        INTEGER (0..max-bindings),
#              variable-bindings  VarBindList
#          }
class GetRequest < RASN1::Model
  sequence :pdu,
           implicit: 0, constructed: true,
           content: [integer(:id, value: 0),
                     enumerated(:error, enum: ERRORS),
                     integer(:error_index),
                     model(:varbindlist, VariableBindings)]
end

# Class to handle GetNextRequest PDU
#  GetNextRequest-PDU ::= [1] IMPLICIT PDU   -- PDU definition: see GetRequest
class GetNextRequest < GetRequest
  # same definition as GetRequest, but change :implicit value
  root_options implicit: 1
end

# Class to handle GetResponse PDU
#  GetResponse-PDU ::= [2] IMPLICIT PDU   -- PDU definition: see GetRequest
class GetResponse < GetRequest
  root_options implicit: 2
end

# Class to handle SetRequest PDU
#  SetRequest-PDU ::= [3] IMPLICIT PDU   -- PDU definition: see GetRequest
class SetRequest < GetRequest
  root_options implicit: 3
end

# Class to handle Trap from SNMPv1
#  Trap-PDU ::= [4] IMPLICIT SEQUENCE {
#                          enterprise OBJECT IDENTIFIER,
#                          agent-addr NetworkAddress,
#                          generic-trap      -- generic trap type
#                              INTEGER {
#                                  coldStart(0),
#                                  warmStart(1),
#                                  linkDown(2),
#                                  linkUp(3),
#                                  authenticationFailure(4),
#                                  egpNeighborLoss(5),
#                                  enterpriseSpecific(6)
#                              },
#                          specific-trap INTEGER,
#                          time-stamp TimeTicks,
#                          variable-bindings VarBindList
#                   }
class Trapv1 < RASN1::Model
  sequence :trap,
           implicit: 4, constructed: true,
           content: [objectid(:enterprise),
                     octet_string(:agent_addr),
                     enumerated(:generic_trap, enum: { 'cold_start'        => 0,
                                                       'warm_start'        => 1,
                                                       'link_down'         => 2,
                                                       'link_up'           => 3,
                                                       'auth_failure'      => 4,
                                                       'egp_neighbor_loss' => 5,
                                                       'specific'          => 6 }),
                     integer(:specific_trap),
                     integer(:timestamp),
                     model(:varbindlist, VariableBindings)]
end

# Class to handle Bulk PDU
#  GetBulkRequest-PDU ::= [5] IMPLICIT BulkPDU
#  
#  BulkPDU ::=                         -- must be identical in
#        SEQUENCE {                    -- structure to PDU
#            request-id        INTEGER (-214783648..214783647),
#            non-repeaters     INTEGER (0..max-bindings),
#            max-repetitions   INTEGER (0..max-bindings),
#            variable-bindings VarBindList
#        }
class Bulk < RASN1::Model
  sequence :bulkpdu,
           implicit: 5, constructed: true,
           content: [integer(:id, value: 0),
                     integer(:non_repeaters),
                     integer(:max_repetitions),
                     model(:varbindlist, VariableBindings)]
end

# Class to handle InformRequest PDU
#  InformRequest-PDU ::= [6] IMPLICIT PDU   -- PDU definition: see GetRequest
class InformRequest < GetRequest
  root_options implicit: 6
end

# Class to handle Trapv2 PDU
#  SNMPv2-Trap-PDU ::= [7] IMPLICIT PDU   -- PDU definition: see GetRequest
class Trapv2 < GetRequest
  root_options implicit: 7
end

# Class to handle Report PDU
#  Report-PDU ::= [8] IMPLICIT PDU   -- PDU definition: see GetRequest
class Report < GetRequest
  root_options implicit: 8
end

# Class to handle PDUs from SNMP packet
#  PDUs ::= CHOICE {
#             get-request      [0] IMPLICIT PDU,
#             get-next-request [1] IMPLICIT PDU,
#             get-response     [2] IMPLICIT PDU,
#             set-request      [3] IMPLICIT PDU,
#             snmpV1-trap      [4] IMPLICIT PDU,
#             get-bulk-request [5] IMPLICIT PDU,
#             inform-request   [6] IMPLICIT PDU,
#             snmpV2-trap      [7] IMPLICIT PDU,
#             report           [8] IMPLICIT PDU
#           }
class PDUs < RASN1::Model
  choice :pdus,
         content: [model(:get_request, GetRequest),
                   model(:get_next_request, GetNextRequest),
                   model(:get_response, GetResponse),
                   model(:set_request, SetRequest),
                   model(:trapv1, Trapv1),
                   model(:bulk, Bulk),
                   model(:inform, InformRequest),
                   model(:trapv2, Trapv2),
                   model(:report, Report)]
end

class SNMP < RASN1::Model
  sequence :message,
           content: [enumerated(:version, value: 'v2c',
                                enum: { 'v1' => 0, 'v2c' => 1, 'v2' => 2, 'v3' => 3 }),
                     octet_string(:community, value: 'public'),
                     model(:data, PDUs)]
end

Clone this wiki locally