Module: SNMP::BER::Decode

Included in:
Integer, Message, ObjectId, PDU, SNMPv1_Trap, VarBind, VarBindList
Defined in:
lib/snmp/ber.rb

Instance Method Summary collapse

Instance Method Details

#assert_no_remainder(remainder) ⇒ Object

Raises:


84
85
86
# File 'lib/snmp/ber.rb', line 84

def assert_no_remainder(remainder)
  raise ParseError, remainder.inspect if remainder != ""
end

#build_integer(data, start, num_octets) ⇒ Object


157
158
159
160
161
# File 'lib/snmp/ber.rb', line 157

def build_integer(data, start, num_octets)
  number = 0
  num_octets.times { |i| number = number<<8 | data[start+i].ord }
  return number
end

#decode_integer(data) ⇒ Object

Decode TLV data for an ASN.1 integer.

Throws an InvalidTag exception if the tag is incorrect.

Returns a tuple containing an integer and any remaining unprocessed data.

Raises:


128
129
130
131
132
# File 'lib/snmp/ber.rb', line 128

def decode_integer(data)
  tag, value, remainder = decode_tlv(data)
  raise InvalidTag, tag.to_s if tag != INTEGER_TAG
  return decode_integer_value(value), remainder
end

#decode_integer_value(value) ⇒ Object


140
141
142
143
144
145
146
# File 'lib/snmp/ber.rb', line 140

def decode_integer_value(value)
  result = build_integer(value, 0, value.length)
  if value[0].ord[7] == 1
    result -= (1 << (8 * value.length))
  end
  result
end

#decode_ip_address(data) ⇒ Object

Raises:


176
177
178
179
180
181
# File 'lib/snmp/ber.rb', line 176

def decode_ip_address(data)
  tag, value, remainder = decode_tlv(data)
  raise InvalidTag, tag.to_s if tag != IpAddress_TAG
  raise InvalidLength, tag.to_s if value.length != 4
  return value, remainder
end

#decode_object_id(data) ⇒ Object

Unwrap TLV data for an ASN.1 object identifier. This method extracts the OID value as a character string but does not decode it further.

Throws an InvalidTag exception if the tag is incorrect.

Returns a tuple containing the object identifier (OID) and any remaining unprocessed data. The OID is represented as an array of integers.

Raises:


207
208
209
210
211
# File 'lib/snmp/ber.rb', line 207

def decode_object_id(data)
  tag, value, remainder = decode_tlv(data)
  raise InvalidTag, tag.to_s if tag != OBJECT_IDENTIFIER_TAG
  return decode_object_id_value(value), remainder
end

#decode_object_id_value(value) ⇒ Object


213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/snmp/ber.rb', line 213

def decode_object_id_value(value)
  if value.length == 0
    object_id = []
  else
    value0 = value[0].ord
    if value0 == 0x2b
      object_id = [1,3]
    else
      second = value0 % 40
      first = (value0 - second) / 40
      raise InvalidObjectId, value.to_s if first > 2
      object_id = [first, second]
    end
    n = 0
    for i in 1...value.length
      n = (n<<7) + (value[i].ord & 0x7f)
      if value[i].ord < 0x80
        object_id << n
        n = 0
      end
    end
  end
  return object_id
end

#decode_octet_string(data) ⇒ Object

Decode TLV data for an ASN.1 octet string.

Throws an InvalidTag exception if the tag is incorrect.

Returns a tuple containing a string and any remaining unprocessed data.

Raises:


170
171
172
173
174
# File 'lib/snmp/ber.rb', line 170

def decode_octet_string(data)
  tag, value, remainder = decode_tlv(data)
  raise InvalidTag, tag.to_s if tag != OCTET_STRING_TAG
  return value, remainder
end

#decode_sequence(data) ⇒ Object

Decode TLV data for an ASN.1 sequence.

Throws an InvalidTag exception if the tag is incorrect.

Returns a tuple containing the sequence data and any remaining unprocessed data that follows the sequence.

Raises:


191
192
193
194
195
# File 'lib/snmp/ber.rb', line 191

def decode_sequence(data)
  tag, value, remainder = decode_tlv(data)
  raise InvalidTag, tag.to_s if tag != SEQUENCE_TAG
  return value, remainder
end

#decode_timeticks(data) ⇒ Object

Raises:


134
135
136
137
138
# File 'lib/snmp/ber.rb', line 134

def decode_timeticks(data)
  tag, value, remainder = decode_tlv(data)
  raise InvalidTag, tag.to_s if tag != TimeTicks_TAG
  return decode_uinteger_value(value), remainder
end

#decode_tlv(data) ⇒ Object

Decode tag-length-value data. The data is assumed to be a string of bytes in network byte order. This format is returned by Socket#recv.

Returns a tuple containing the tag, the value, and any remaining unprocessed data.

The data is not interpretted by this method. Use one of the other decoding methods to interpret the data.

Note that ASN.1 supports an indefinite length format where the end of content is marked by a pair of 0 octets. SNMP does not support this format, so only the two definite forms are implemented (single byte and multi-byte).

Raises:


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/snmp/ber.rb', line 103

def decode_tlv(data)
  raise OutOfData if (data.length == 2 && data[1].ord != 0) || data.length < 2
  tag = data[0].ord
  length = data[1].ord
  if length < 0x80
    value = data[2, length]
    remainder = data[length+2..-1]
  else
    # ASN.1 says this octet can't be 0xff
    raise InvalidLength, length.to_s if length == 0xff
    num_octets = length & 0x7f
    length = build_integer(data, 2, num_octets)
    value = data[num_octets+2, length]
    remainder = data[num_octets+2+length..-1]
  end
  return tag, value, remainder
end

#decode_uinteger_value(value) ⇒ Object

Decode an integer, ignoring the sign bit. Some agents insist on encoding 32 bit unsigned integers with four bytes even though it should be 5 bytes (at least the way I read it).


153
154
155
# File 'lib/snmp/ber.rb', line 153

def decode_uinteger_value(value)
  build_integer(value, 0, value.length)
end