locked
snmp module, working with byte array RRS feed

  • Question

  • I'm quering the snmp of printers using a powershell snmp module (https://www.powershellgallery.com/packages/SNMP/1.0.0.1).  I'm asking for hrPrinterDetectedErrorState  or OID '1.3.6.1.2.1.25.3.5.1.2.1'.  It returns the data as a string, but it's really a byte array I think.  How do I convert that to an integer I can use, and check which bits are set to print the right messages?

    Here's how to make an example.  So $b is an example of what I could get back from the data property of the command (it prints it as an exclamation point which is ascii 33):

    "Get-SnmpData -v v1 -ip $ip -oid 1.3.6.1.2.1.25.3.5.1.2.1"

    $a = [byte[]](33,0,0,0)
    $b = [string][char[]]$a
    $b
    
    !


    I've tried "[bitconverter]::ToInt16([char[]]$b ,0)", but that only works if the length is at least 2 bytes, and it could be 1 or 4 bytes.  What's the normal way to handle things like this?

    Here's how the output looks:

    Get-SnmpData -v v1 -ip $ip -oid 1.3.6.1.2.1.25.3.5.1.2.1
    
    OID                       Data
    ---                       ----
    .1.3.6.1.2.1.25.3.5.1.2.1 !




    • Edited by JS2010 Saturday, February 17, 2018 9:55 PM
    Saturday, February 17, 2018 6:00 PM

All replies

  • The "Data" is set to 1 (the number 1).  This is the error state.  I assum 1 means error and 0 means no error.

    To get only the raw data:

    Get-SnmpData -v v1 -ip $ip -oid 1.3.6.1.2.1.25.3.5.1.2.1 | Select -Expand Data


    \_(ツ)_/

    Saturday, February 17, 2018 6:07 PM
  • In this case it's a sum of numbers from [math]::pow(2,0) to [math]::pow(2,14).  https://community.pharos.com/servlet/JiveServlet/downloadBody/2429-102-3-5922/TechNote%20Checking%20Device%20Status.pdf

    The data appears as an explanation point.  So 33 in decimal would be '(not used)' and 'markerSupplyMissing'.

    I guess i'm asking how to convert a variable length byte array to an integer, so that these statements are true:

    [math]::pow(2,0) -band $data
    [math]::pow(2,5) -band $data
    


    • Edited by JS2010 Saturday, February 17, 2018 6:28 PM
    Saturday, February 17, 2018 6:17 PM
  • There are no text encoded data elements from SNMP.  If it is a string then it is text.  If it an integer then it is a number and if it is a byte array the "Data" contains a list of bytes.  "hrPrinterDetectedErrorState " is an integer representation of a flags array..  See: https://www.zabbix.com/forum/archive/index.php/t-11594.html

    OID                                    Data
    ---                                     ----
    .1.3.6.1.2.1.25.3.5.1.2.1        !

    Note that "Data" is "1" and is an integer.

    "1" means low paper.


    \_(ツ)_/

    Saturday, February 17, 2018 6:30 PM
  • The data is an explanation point in this case.  That snmp module always returns the data as a string.  The length of it is 4.  I can convert it into [char[]] then [byte[]] and it becomes (33,0,0,0).


    • Edited by JS2010 Saturday, February 17, 2018 6:39 PM
    Saturday, February 17, 2018 6:34 PM
  • No.  The Data is a stream of bytes and has a type which tells any SNMP module how to interpret the bytes.  It is system independent.  THe Data in the case contains a "1" value and is likely defined as an integer.  The link I posted shows how to use the OID value.

    See:

    a) hrPrinterDetectedErrorState is defined in the HOST-RESOURCES-MIB
    (RFC 2790) and on in the Printer-MIB
    
    b) The current version of the Printer-MIB is RFC 3805 and not RFC 1759.
    
    c) hrPrinterDetectedErrorState as currentely defined returns an octet
    not a character and it might actually return multiple octets in a
    future revision.

    It is an octet which is an 8 bit number.  It is not a character.  The newer versions return 4 octets and read as octets we would have a dot separated quad.

    This one should be 1.0.0.0 or 0.0.0.1 and leading zeros are suppressed.   An octet is numeric.  Octets can contain characters and would need tp be converted.  Most SNMP tools do this conversion and display "Data" as a string.  I am not sure if the PowerShell module is that smart.

    Remember computers do not know anything about text.  They only deal in numeric bits, bytes and words.

    Look up the schema entry for that OID and it will tell you what is encoded in the octet data field and how to decode it.


    \_(ツ)_/

    Saturday, February 17, 2018 7:07 PM
  • Just copy and paste it and do '!' -eq 1.  It's an explanation point (ascii 33).  I understand it's supposed to be a set of bytes, but the module returns it as a string according to gettype().

    snmpget in osx prints it as "Hex-STRING: 21 00 00 00".

    • Edited by JS2010 Saturday, February 17, 2018 7:19 PM
    Saturday, February 17, 2018 7:11 PM
  • What is an 'explanation point".  What does that have to do with printer error status fields?

     

    \_(ツ)_/

    Saturday, February 17, 2018 7:25 PM
  • To convert an arbitrary length byte array to ascii we would use the text converter.

    [System.Text.Encoding]::ASCII.GetString($bytes)

    If the bytes are Unicode then use:

    [System.Text.Encoding]::Unicode.GetString($bytes)


    \_(ツ)_/

    Saturday, February 17, 2018 7:29 PM
  • The Data property here is an explanation point:

    OID                           Data
    ---                           ----
    .1.3.6.1.2.1.25.3.5.1.2.1     !


    • Edited by JS2010 Saturday, February 17, 2018 7:40 PM
    Saturday, February 17, 2018 7:39 PM
  • You mena "exclamation point".  Now I see what you mean.

    That is because the PS library is converting it to a string for display.  The actual data is an array of octets.  Read them as bytes by converting to bytes.

     [System.Text.Encoding]::ASCII.GetBytes($bytes)

    $results = Get-SnmpData -v v1 -ip $ip -oid 1.3.6.1.2.1.25.3.5.1.2.1
    [System.Text.Encoding]::ASCII.GetBytes($results.Data)

    The packet data has the data type and length which should be set in the result object:

    Get-SnmpData -v v1 -ip $ip -oid 1.3.6.1.2.1.25.3.5.1.2.1 | Select *

    This will tell you how to decode the "Data" property.


    \_(ツ)_/

    Saturday, February 17, 2018 7:49 PM
  • I'll just use if statements for now.  This gives me what I want.


    if ($data.length -eq 4) { $data = [bitconverter]::ToInt32([char[]]$data ,0) }
    if ($data.length -eq 2) { $data = [bitconverter]::ToInt16([char[]]$data ,0) }
    if ($data.length -eq 1) { $data = [int][char]$data } 


    EDIT:  this turned out to be wrong.  The bytes were going in backwards.



    • Edited by JS2010 Thursday, March 1, 2018 9:19 PM
    Saturday, February 17, 2018 7:53 PM
  • Here is the full API structure definition of the returned ASN. The SNMP module should add this and allow the returned objects to be correctly decoded.

    Each ASN has all of the information to know how it needs to be decoded.  Each ASN has a "Type" as the first field and it specifies all integer, counter and other types used in SNMP query data returns.

    https://msdn.microsoft.com/en-us/library/windows/desktop/aa377952(v=vs.85).aspx


    \_(ツ)_/

    Saturday, February 17, 2018 8:26 PM
  • Just an additional note.  For this field in snmp (hrPrinterDetectedErrorState), sometimes only one byte instead of two are returned.  So you can't treat it as a typical bitmask without some additional processing.


    • Edited by JS2010 Friday, February 23, 2018 4:59 PM
    Friday, February 23, 2018 4:52 PM