puresnmp icon indicating copy to clipboard operation
puresnmp copied to clipboard

puresnmp.exc.ErrorResponse: unknown error (status-code: 17) on OID 1.3.6.1.2.1.1.4.0

Open beruhan opened this issue 5 years ago • 6 comments

I use the example in the doc,but I raise exception:

from puresnmp import set
    from puresnmp.x690.types import OctetString

    IP = "192.168.12.133"
    COMMUNITY = 'private'
    OID = '1.3.6.1.2.1.1.4.0'

    result = set(IP, COMMUNITY, OID, OctetString(b'I am contact'))
    print(repr(result))

the exception as follows:

Traceback (most recent call last):
  File "D:/work/project/iot_exploit/iot_exploit/core/protocols/snmp_client.py", line 74, in <module>
    result = set(IP, COMMUNITY, OID, OctetString(b'I am contact'))
  File "C:\Python36\lib\site-packages\puresnmp\api\pythonic.py", line 136, in set
    result = multiset(ip, community, [(oid, value)], port, timeout=timeout)
  File "C:\Python36\lib\site-packages\puresnmp\api\pythonic.py", line 149, in multiset
    raw_output = raw.multiset(ip, community, mappings, port, timeout)
  File "C:\Python36\lib\site-packages\puresnmp\api\raw.py", line 321, in multiset
    raw_response = Sequence.from_bytes(response)
  File "C:\Python36\lib\site-packages\puresnmp\x690\types.py", line 170, in from_bytes
    return cls.decode(data)
  File "C:\Python36\lib\site-packages\puresnmp\x690\types.py", line 400, in decode
    value, data = pop_tlv(data)
  File "C:\Python36\lib\site-packages\puresnmp\x690\types.py", line 116, in pop_tlv
    value = cls.from_bytes(chunk)
  File "C:\Python36\lib\site-packages\puresnmp\x690\types.py", line 170, in from_bytes
    return cls.decode(data)
  File "C:\Python36\lib\site-packages\puresnmp\pdu.py", line 231, in decode
    return super(GetResponse, cls).decode(data)
  File "C:\Python36\lib\site-packages\puresnmp\pdu.py", line 117, in decode
    raise exception
puresnmp.exc.ErrorResponse: unknown error (status-code: 17) on OID 1.3.6.1.2.1.1.4.0

beruhan avatar Jul 01 '19 15:07 beruhan

This exception means that the device itself returns an error with the code 17. The meaning of this code is non-standard and should be documented by the device manufacturer. Possibly in MIB files.

But to make sure puresnmp is behaving correctly, can you try to run the following two commands on a Linux CLI and attach the output please?

snmpget -v2c -c <your_community> -On <ip-address> 1.3.6.1.2.1.1.4.0

and

snmpget -v2c -c <your_community> -On <ip-address> .1.3.6.1.2.1.1.4.0

In case this works, double-check that it is still broken in puresnmp. I've come accross some devices that only work... sometimed 😄

exhuma avatar Jul 02 '19 05:07 exhuma

I think it could be related to the case when OID does not exist. In my case the folowing is thrown when code is trying to get one of not exisitng OIDs:

Traceback (most recent call last):

await self.device.snmp_get('1.3.6.1.4.1.32584.1.1.1.12.2.0') File "/usr/lib/preseem/netpoll/snmp_client.py", line 124, in snmp_get val = await psnmp.get(self.host, self.comm, oid) File "/usr/local/lib/python3.7/site-packages/puresnmp/aio/api/raw.py", line 83, in get ip, community, [oid], port, timeout=timeout) File "/usr/local/lib/python3.7/site-packages/puresnmp/aio/api/raw.py", line 112, in multiget Sequence.from_bytes(response) File "/usr/local/lib/python3.7/site-packages/puresnmp/x690/types.py", line 169, in from_bytes return cls.decode(data) File "/usr/local/lib/python3.7/site-packages/puresnmp/x690/types.py", line 382, in decode value, data = pop_tlv(data) File "/usr/local/lib/python3.7/site-packages/puresnmp/x690/types.py", line 117, in pop_tlv value = cls.from_bytes(chunk) File "/usr/local/lib/python3.7/site-packages/puresnmp/x690/types.py", line 169, in from_bytes return cls.decode(data) File "/usr/local/lib/python3.7/site-packages/puresnmp/pdu.py", line 286, in decode return super(GetResponse, cls).decode(data) File "/usr/local/lib/python3.7/site-packages/puresnmp/pdu.py", line 145, in decode raise exception puresnmp.exc.GenErr: General Error (genErr) (status-code: 5) on OID 1.3.6.1.4.1.32584.1.1.1.12.2.0`

When I try to use Linux CLI based snmpget with the same OID it just return nothing.

alexxxe avatar Jun 04 '20 18:06 alexxxe

@alexxxe: the last line in the traceback says that the device returned an SNMP packet with an error-code of "5". These error codes are mapped to Python exceptions and are raised if a device returns such a packet.

There is a special error-status (2) for non-existing OIDs. So it's either incorrectly reported as "general-error" by the device, or the OID exists, and something else is wrong on the device.

I see this comes from a multiget call. And I can see that having the whole call crash out with an exception if only one of the OIDs causes issues like this is a problem. It might be worth retuning the exceptions instances in that case, instead of raising them. This would allow for more graceful degradation of client-code without losing details on errors. I'll think about how to integrate this feature.

exhuma avatar Jun 05 '20 07:06 exhuma

... actally, scratch my last comment about adding a more "forgiving" return value. The error-status is a field in the returning PDU, so unfortunately the whole respose packet is tagged as error and raising an Exception is the correct way of handling this.

exhuma avatar Jun 05 '20 07:06 exhuma

@exhuma , thanks for your response. I thinkg in my case device is incorrectly responsed with error-status: 5 on non-existing OID. And yes, this is still a problem in case when the one not exisiting OID fails the whole call.

alexxxe avatar Jun 08 '20 13:06 alexxxe

I'm actually not sure I can do anything about that. SNMP exchanges messages as "PDU" messages. The error-code is part of the top-level information in that PDU. The requested variables/values are embedded inside that PDU.

The error-status "5" flags the whole PDU as erroneous. So in a way it is correct to raise this as an exception.

Other errors like "NoSuchOID" or "NoSuchInstance" are actually error values which are not written into the PDU error-status field, but rather in the variable value.

I will keep thinking on this. I am currently reading through the SNMPv3 RFCs to get support for that too, but I'm only advancing slowly. But I will need to keep some way in the code to raise errors if something goes wrong on the device. If I will make this more lenient, then devices which correctly return errors might lead to incorrect code/values downstream (in the client code). I prefer to "fail fast".

I understand this is not a solution if you have a device which misbehaves, but which you still want to query via SNMP.

I'm currently using puresnmp on several thousand devices on a daily basis, and I've come across some funky behaviours myself. On those extreme/blocking cases I usually contact the device manufacturer and so far they always agreed that it was a bug in their OS and fixed it.

exhuma avatar Jun 09 '20 15:06 exhuma