Snmp Get
Snmp Get
Anybody has information how to implement this function in PureBasic ?
- Michael Vogel
- Addict
- Posts: 2807
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Re: Snmp Get
Someone did some snmp code in the german forum, using an UDPnetwork lib (which I couldn't install, but this should be possible)...Droopy wrote:Anybody has information how to implement this function in PureBasic ?
http://www.purebasic.fr/german/viewtopi ... light=snmp
- Michael Vogel
- Addict
- Posts: 2807
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Looking for SNMP code examples... anyone that has a suggestion?
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
( The path to enlightenment and the PureBasic Survival Guide right here... )
- Michael Vogel
- Addict
- Posts: 2807
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Would be fine for me also - I used a very rude method: calling SNMPUtil.exe in a hidden window by different threads and capturing its output to memory...blueznl wrote:Looking for SNMP code examples... anyone that has a suggestion?
Indeed not brilliant


But I didn't find a simple method (without libraries) to do SNMP communications by my own (wether as "client" to poll nor as a "server" to simulate network manageable components)
Michael
If you can use WMI in PB you could do this
http://msdn2.microsoft.com/en-us/librar ... S.85).aspx.
I think some people have got this working (WMI that is)
http://msdn2.microsoft.com/en-us/librar ... S.85).aspx.
I think some people have got this working (WMI that is)
Paul Dwyer
“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
“In nature, it’s not the strongest nor the most intelligent who survives. It’s the most adaptable to change” - Charles Darwin
“If you can't explain it to a six-year old you really don't understand it yourself.” - Albert Einstein
SNMP GET and GET_NEXT
Not finished, but functional
You may help me to finish it
Not finished, but functional
You may help me to finish it
Code: Select all
Procedure.l Set_Integer ( value.l )
If value <= $7F
*Integer = AllocateMemory ( 1 )
PokeB ( *Integer, value )
Else
*Integer = AllocateMemory ( 2 )
PokeB ( *Integer + 00, ( value & $FF00 ) >> 8 )
PokeB ( *Integer + 01, value & $FF )
EndIf
ProcedureReturn *Integer
EndProcedure
Procedure.l Get_Integer ( *Integer, free_memory.l )
value = 0
For position = 0 To MemorySize ( *Integer ) - 1
value.l = ( x_value << 8 ) | PeekB ( *Integer + position )
Next
If free_memory = #True
FreeMemory ( *Integer )
EndIf
ProcedureReturn value
EndProcedure
Procedure.l BER_Encode ( value.q )
*BER_Encode = #Null
If value >= 0 And value < 128
*BER_Encode = AllocateMemory ( 1 )
PokeB ( *BER_Encode + 00, value )
ElseIf value >= 128 And value < 16384
*BER_Encode = AllocateMemory ( 2 )
PokeB ( *BER_Encode + 00, $80 | ( value >> 7 ) )
PokeB ( *BER_Encode + 01, value & $7f )
ElseIf value >= 16384 And value < 2097152
*BER_Encode = AllocateMemory ( 3 )
PokeB ( *BER_Encode + 00, $80 | ( ( value >> 14 ) & $7f ) )
PokeB ( *BER_Encode + 01, $80 | ( ( value >> 7 ) & $7f ) )
PokeB ( *BER_Encode + 02, value & $7f )
ElseIf value >= 2097152 And value < 268435456
*BER_Encode = AllocateMemory ( 4 )
PokeB ( *BER_Encode + 00, $80 | ( ( value >> 21 ) & $7f ) )
PokeB ( *BER_Encode + 01, $80 | ( ( value >> 14 ) & $7f ) )
PokeB ( *BER_Encode + 02, $80 | ( ( value >> 7 ) & $7f ) )
PokeB ( *BER_Encode + 03, value & $7f )
ElseIf value >= 268435456 And value < 4294967296
*BER_Encode = AllocateMemory ( 5 )
PokeB ( *BER_Encode + 00, $80 | ( ( value >> 28 ) & $0f ) )
PokeB ( *BER_Encode + 01, $80 | ( ( value >> 21 ) & $7f ) )
PokeB ( *BER_Encode + 02, $80 | ( ( value >> 14 ) & $7f ) )
PokeB ( *BER_Encode + 03, $80 | ( ( value >> 7 ) & $7f ) )
PokeB ( *BER_Encode + 04, value & $7f )
EndIf
ProcedureReturn *BER_Encode
EndProcedure
Procedure.l BER_Decode_2 ( *input_data, cut.l, free_memory.l )
output_value.l = 0
value_1.l = PeekB( *input_data + 00 ) & $FF
value_2.l = PeekB( *input_data + 01 ) & $FF
counter.l = 2
If value_1 = $80
output_value = $80
ElseIf value_1 > $80 And value_2 > $80
output_value = ( ( value_1 - $80 ) << 7 ) + ( value_2 - $80 )
ElseIf value_1 > $80 And value_2 < $80
output_value = ( ( value_1 - $80 ) << 7 ) + value_2
ElseIf value_1 < $80
output_value = value_1
counter = 1
EndIf
If cut = #True
CopyMemory ( *input_data + counter , *input_data, MemorySize ( *input_data ) - counter )
ReAllocateMemory ( *input_data, MemorySize ( *input_data ) - counter )
EndIf
If free_memory = #True
FreeMemory ( *input_data )
EndIf
ProcedureReturn output_value
EndProcedure
Procedure.l OID_Encode ( oid_string.s )
dot_numbers = CountString ( oid_string, "." )
*OID_Encode = AllocateMemory ( 1024 )
OID_Encode_Length = 0
If Left ( oid_string, 1 ) = "."
oid_string = Mid ( oid_string, 2, Len ( oid_string ) - 1 )
EndIf
first = Val ( StringField( oid_string, 1, "." ) )
second = Val ( StringField( oid_string, 2, "." ) )
first = ( first * 40 ) + second
*mem_value = BER_Encode ( first )
CopyMemory ( *mem_value, *OID_Encode, MemorySize ( *mem_value ) )
OID_Encode_Length + MemorySize ( *mem_value )
FreeMemory ( *mem_value )
If CountString ( oid_string, "." ) > 1
For position.l = 3 To dot_numbers + 1
*mem_value = BER_Encode ( Val ( StringField( oid_string, position, "." ) ) )
CopyMemory ( *mem_value, *OID_Encode + OID_Encode_Length, MemorySize ( *mem_value ) )
OID_Encode_Length + MemorySize ( *mem_value )
FreeMemory ( *mem_value )
Next
EndIf
ReAllocateMemory ( *OID_Encode, OID_Encode_Length )
ProcedureReturn *OID_Encode
EndProcedure
Procedure.s OID_Decode ( *OID_Decode )
Dim OID.l ( 256 )
OID_string.s = ""
OID_count = 1
subid = 0
For counter = 0 To MemorySize ( *OID_Decode ) - 1
value = PeekB( *OID_Decode + counter ) & $FF
If subid & $FE000000
Debug "object too large"
EndIf
subid = ( subid << 7 ) | ( value & $7F )
If Not( value & $80 )
OID ( OID_count ) = subid
OID_count + 1
subid = 0
EndIf
Next
If OID ( 1 ) = 43
OID ( 0 ) = 1
OID ( 1 ) = 3
ElseIf OID ( 1 ) < 64
OID ( 0 ) = 0
ElseIf OID ( 1 ) < 128
OID ( 0 ) = 1
OID ( 1 ) = 64
Else
OID ( 0 ) = 2
OID ( 1 ) = 128
EndIf
For counter = 0 To OID_count - 1
OID_string + "." + Str( OID ( counter ) )
Next
ProcedureReturn OID_string
EndProcedure
Procedure.l Make_TLV ( type.b, *input_data, free_memory.l )
Data_Length.l = MemorySize ( *input_data )
*Octet_Length = Set_Integer ( Data_Length )
Length.l = MemorySize ( *Octet_Length )
*TLV = AllocateMemory ( 1 + Length + Data_Length )
PokeB ( *TLV, type )
CopyMemory ( *Octet_Length, *TLV + 1 , Length)
CopyMemory ( *input_data , *TLV + 1 + Length, Data_Length )
FreeMemory ( *Octet_Length )
If free_memory = #True
FreeMemory ( *input_data )
EndIf
ProcedureReturn *TLV
EndProcedure
Procedure.l Make_TLV_Null ( type.b )
*TLV = AllocateMemory ( 2 )
PokeB ( *TLV + 00, type )
PokeB ( *TLV + 01, 00 )
ProcedureReturn *TLV
EndProcedure
Procedure.l Join_Data ( *memory_1, *memory_2, free_memory.l )
*Joined = AllocateMemory ( MemorySize ( *memory_1 ) + MemorySize ( *memory_2 ) )
CopyMemory ( *memory_1, *Joined, MemorySize ( *memory_1 ) )
CopyMemory ( *memory_2, *Joined + MemorySize ( *memory_1 ), MemorySize ( *memory_2 ) )
If free_memory = #True
FreeMemory ( *memory_1 )
FreeMemory ( *memory_2 )
EndIf
ProcedureReturn *Joined
EndProcedure
Procedure.l Make_String ( string.s )
*String = AllocateMemory ( Len (string) )
PokeS ( *String, string )
ProcedureReturn *String
EndProcedure
Procedure.l Memory_Move_Left ( *memory, offset.l )
If MemorySize ( *memory ) > offset
CopyMemory ( *memory + offset, *memory, MemorySize ( *memory ) - offset )
ReAllocateMemory ( *memory, MemorySize ( *memory ) - offset )
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Procedure.l Unpack_TLV ( *input_data, cut_memory.l, free_memory.l )
*TMP = AllocateMemory ( MemorySize ( *input_data ) - 1 )
CopyMemory ( *input_data + 1, *TMP, MemorySize ( *TMP ) )
type.l = PeekB ( *input_data ) & $FF
return_value = #False
cut_length = 0
If type = $05
cut_length = 2
ElseIf type = $30 Or type > $9F
; SEQUENCE
sequence_length = BER_Decode_2 ( *TMP, #True, #False )
If sequence_length = MemorySize ( *TMP )
return_value = *TMP
EndIf
Else
; Other
Length = PeekB ( *TMP ) & $FF
Memory_Move_Left ( *TMP, 1 )
ReAllocateMemory ( *TMP, Length )
return_value = *TMP
cut_length = 2 + Length
EndIf
If cut_memory = #True
Memory_Move_Left ( *input_data, cut_length )
EndIf
If free_memory = #True
FreeMemory ( *input_data )
EndIf
ProcedureReturn return_value
EndProcedure
Procedure.l Make_SNMP_Packet ( community_string.s, snmp_pdu.s, request_id.l, object_identifier.s )
return_value = #False
If UCase ( snmp_pdu ) = "GET_NEXT"
SNMP_PDU_Type.l = $A1
*Value = Make_TLV_Null ( $05 )
Else ; GET
SNMP_PDU_Type.l = $A0
*Value = Make_TLV_Null ( $05 )
EndIf
; [ SNMP_Message [ Version_Number ] [ Community_String ] [ SNMP_PDU [ Request_ID ] [ Error ] [ Error_Index ] [ Varbind_List [ Varbind [ Object_Identifier ] [ Value ] ] ] ] ]
*OID = OID_Encode ( object_identifier )
If *OID
*Object_Identifier = Make_TLV ( $06, *OID, #True )
EndIf
If *Object_Identifier And *Value
*Varbind_Data = Join_Data ( *Object_Identifier, *Value, #True )
EndIf
If *Varbind_Data
*Varbind = Make_TLV ( $30, *Varbind_Data, #True )
EndIf
If *Varbind
*Varbind_List = Make_TLV ( $30, *Varbind, #True )
*Request_ID_Value = Set_Integer ( request_id )
EndIf
If *Request_ID_Value And *Varbind_List
*Request_ID = Make_TLV ( $02, *Request_ID_Value, #True )
*Error_Value = Set_Integer ( $00 )
EndIf
If *Request_ID And *Error_Value
*Error = Make_TLV ( $02, *Error_Value, #True )
*Error_Index_Value = Set_Integer ( $00 )
EndIf
If *Error And *Error_Index_Value
*Error_Index = Make_TLV ( $02, *Error_Index_Value, #True )
*Temp_1 = Join_Data ( *Request_ID, *Error, #True )
EndIf
If *Error_Index And *Temp_1
*Temp_2 = Join_Data ( *Temp_1, *Error_Index, #True )
EndIf
If *Temp_2
*SNMP_PDU_Data = Join_Data ( *Temp_2, *Varbind_List, #True )
EndIf
If *SNMP_PDU_Data
*SNMP_PDU = Make_TLV ( SNMP_PDU_Type, *SNMP_PDU_Data, #True )
*SNMP_Community_String_Value = Make_String ( community_string )
EndIf
If *SNMP_PDU And *SNMP_Community_String_Value
*SNMP_Community_String = Make_TLV ( $04, *SNMP_Community_String_Value, #True )
*SNMP_Version_Value = Set_Integer ( $00 )
EndIf
If *SNMP_Community_String And *SNMP_Version_Value
*SNMP_Version = Make_TLV ( $02, *SNMP_Version_Value, #True )
EndIf
If *SNMP_Version
*Temp_3 = Join_Data ( *SNMP_Version, *SNMP_Community_String, #True )
EndIf
If *Temp_3
*SNMP_Message_Data = Join_Data ( *Temp_3, *SNMP_PDU, #True )
EndIf
If *SNMP_Message_Data
*SNMP_Message = Make_TLV ( $30, *SNMP_Message_Data, #True )
return_value = *SNMP_Message
EndIf
ProcedureReturn return_value
EndProcedure
Procedure.l Unpack_SNMP_Response ( *SNMP_Packet, request_id.l )
return_value = #False
*SNMP_Message = Unpack_TLV ( *SNMP_Packet, #True, #False )
If *SNMP_Message
*SNMP_Version = Unpack_TLV ( *SNMP_Message, #True, #False )
If *SNMP_Version
*SNMP_Community = Unpack_TLV ( *SNMP_Message, #True, #False )
If *SNMP_Community
SNMP_Version_Value.l = Get_Integer ( *SNMP_Version, #True )
SNMP_Community_Value.s = PeekS ( *SNMP_Community, MemorySize ( *SNMP_Community ) )
FreeMemory ( *SNMP_Community )
*SNMP_PDU = Unpack_TLV ( *SNMP_Message, #True, #True )
If *SNMP_PDU
*Request_ID = Unpack_TLV ( *SNMP_PDU, #True, #False )
*Error = Unpack_TLV ( *SNMP_PDU, #True, #False )
*Error_Index = Unpack_TLV ( *SNMP_PDU, #True, #False )
*Varbind_List = Unpack_TLV ( *SNMP_PDU, #True, #True )
Request_ID = Get_Integer ( *Request_ID, #True )
; Debug Request_ID
If *Varbind_List
*Varbind = Unpack_TLV ( *Varbind_List, #True, #True )
return_value = *Varbind
EndIf
EndIf
EndIf
EndIf
EndIf
ProcedureReturn return_value
EndProcedure
Procedure.l SNMP_Send_And_Receieve ( ip_address.s, community.s, oid.s, type.s)
return_value.l = #False
If ip_address <> ""
*ptr = sockinfo.sockaddr_in
sockinfo\sin_family = #AF_INET
sockinfo\sin_port = htons_(161)
sockinfo\sin_addr = inet_addr_(ip_address)
SockIdent = SOCKET_(#AF_INET, 2, 0) ;create socket (#SOCK_DGRAM for UDP)
If SockIdent = #INVALID_SOCKET
; Debug "Socket cant be created!"
Else
; Debug "UDP socket created!"
RandomSeed ( Random ( 99999 ) )
Request_ID = Random ( 99999 )
*packet = Make_SNMP_Packet ( community, type, Request_ID, oid )
If *packet
packet_length = MemorySize ( *packet )
send = sendto_(SockIdent, *packet, packet_length, 0, *ptr, SizeOf(sockaddr_in))
If send <> #SOCKET_ERROR
*recv_buffer = AllocateMemory ( 512 )
If *recv_buffer
recv_buffer_size = MemorySize ( *recv_buffer )
start = Date ()
Repeat
Delay(1)
bytesRecv = recv_(SockIdent, *recv_buffer, recv_buffer_size, 2)
If Date () - start > 5
bytesRecv = #SOCKET_ERROR
Break
EndIf
Until bytesRecv <> -1
If bytesRecv <> #SOCKET_ERROR
ReAllocateMemory(*recv_buffer, bytesRecv)
*value = Unpack_SNMP_Response ( *recv_buffer, Request_ID )
If *value
return_value = *value
EndIf
EndIf
FreeMemory ( *recv_buffer )
EndIf
EndIf
FreeMemory (*packet)
EndIf
EndIf
EndIf
ProcedureReturn return_value
EndProcedure
Procedure.l Decode_Result ( *result )
type = PeekB ( *result + 00 ) & $FF
length = PeekB ( *result + 01 ) & $FF
If type = $06
*oid = AllocateMemory (length)
CopyMemory (*result + 2, *oid, length)
oid_s.s = OID_Decode ( *oid )
FreeMemory ( *oid )
Debug oid_s
Memory_Move_Left ( *result, length + 2 )
EndIf
type = PeekB ( *result + 00 ) & $FF
length = PeekB ( *result + 01 ) & $FF
If type = $04 And length > 0
*tmp = AllocateMemory ( length )
CopyMemory ( *result + 2, *tmp, length)
Debug PeekS ( *tmp, length )
EndIf
FreeMemory ( *result )
EndProcedure
Procedure ping (sIPAddress.s)
EchoMessage.s = "Echo"
ResultSize.l = SizeOf(ICMP_ECHO_REPLY) + Len(EchoMessage)
*Result = AllocateMemory(ResultSize)
*Echo.ICMP_ECHO_REPLY = *Result
result = #False
If Len(sIPAddress ) > 0
hFile.l = IcmpCreateFile_()
IPAddress.l = MakeIPAddress(Val(StringField(sIPAddress,1,".")),Val(StringField(sIPAddress,2,".")),Val(StringField(sIPAddress,3,".")),Val(StringField(sIPAddress+".",4,".")))
lngResult.l = IcmpSendEcho_(hFile, IPAddress, EchoMessage, Len(EchoMessage), 0, *Result, ResultSize, 500)
If lngResult
result = #True
; Debug ("Ping " + sIPAddress + " Octets: " + Str(*Echo\DataSize) + " Temps: " + Str(*Echo\RoundTripTime) + " ms TTL:" + StrU(*Echo\Options\Ttl,#Byte))
EndIf
IcmpCloseHandle_(hFile)
EndIf
FreeMemory(*Result)
ProcedureReturn result
EndProcedure
If InitNetwork()
IPAddress.s = "192.168.1.25"
Debug IPAddress
If ping (IPAddress)
*rec = SNMP_Send_And_Receieve ( IPAddress, "public", "1.3.6.1.2.1.1.1.0", "GET") ; or GET_NEXT
If *rec
Decode_Result ( *rec )
EndIf
EndIf
Debug "------------------"
EndIf
Last edited by peterb on Fri Feb 29, 2008 4:05 pm, edited 1 time in total.
- Michael Vogel
- Addict
- Posts: 2807
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Please help me!
I cant get the code to work! I'll get a correct response from the device, but decoding seems to be the problem.
I added some debug lines to find out, where the problem occurs - but then it got too complicate for me
Maybe someone can give me a clue - I'll give you all the information I have:
1. the response packet (taken from an analyzer)
2. the debug output
3. The code // only some debug-lines have been added...
[/list]
I cant get the code to work! I'll get a correct response from the device, but decoding seems to be the problem.
I added some debug lines to find out, where the problem occurs - but then it got too complicate for me

Maybe someone can give me a clue - I'll give you all the information I have:
1. the response packet (taken from an analyzer)
Code: Select all
00 02 3F B1 4E AF 00 0E 6A CC 32 28 08 00 45 00 ..?±N¯..jÌ2(..E.
00 6A 01 A2 00 00 40 11 63 E0 AC 10 DE DE AC 10 .j.¢..@.cà¬.ÞÞ¬.
DE 01 00 A1 0C 23 00 56 32 96 30 82 00 4A 02 01 Þ..¡.#.V2?0?.J..
00 04 06 70 75 62 6C 69 63 A2 82 00 3B 02 02 A1 ...public¢?.;..¡
C9 02 01 00 02 01 00 30 82 00 2D 30 82 00 29 06 É......0?.-0?.).
08 2B 06 01 02 01 01 01 00 04 1D 42 72 6F 61 64 .+.........Broad
62 61 6E 64 20 52 65 73 69 64 65 6E 74 69 61 6C band Residential
20 47 61 74 65 77 61 79 Gateway
Code: Select all
172.16.222.222
PING OK
S&R I: 0'30' ‚'82' J'4A' '2' '1' '4' '6' p'70' u'75' b'62' l'6C' i'69' c'63' ¢'A2' ‚'82' ;'3B' '2' '2' '17' æ'E6' '2' '1' '2' '1' 0'30' ‚'82' -'2D' 0'30' ‚'82' )'29' '6' '8' +'2B'
Unpack I: 0'30' ‚'82' J'4A' '2' '1' '4' '6' p'70' u'75' b'62' l'6C' i'69' c'63' ¢'A2' ‚'82' ;'3B' '2' '2' '17' æ'E6' '2' '1' '2' '1' 0'30' ‚'82' -'2D' 0'30' ‚'82' )'29' '6' '8' +'2B'
TLV I: ‚'82' J'4A' '2' '1' '4' '6' p'70' u'75' b'62' l'6C' i'69' c'63' ¢'A2' ‚'82' ;'3B' '2' '2' '17' æ'E6' '2' '1' '2' '1' 0'30' ‚'82' -'2D' 0'30' ‚'82' )'29' '6' '8' +'2B' '6'
TLV II: J'4A' '2' '1' '4' '6' p'70' u'75' b'62' l'6C' i'69' c'63' ¢'A2' ‚'82' ;'3B' '2' '2' '17' æ'E6' '2' '1' '2' '1' 0'30' ‚'82' -'2D' 0'30' ‚'82' )'29' '6' '8' +'2B' '6' '1' '2'
ÖHA?256 / 75
Cut: 0'30' ‚'82' J'4A' '2' '1' '4' '6' p'70' u'75' b'62' l'6C' i'69' c'63' ¢'A2' ‚'82' ;'3B' '2' '2' '17' æ'E6' '2' '1' '2' '1' 0'30' ‚'82' -'2D' 0'30' ‚'82' )'29' '6' '8' +'2B'
Return: - <<EMPTY>>
Unpack II: - <<EMPTY>>
S&R II: - <<EMPTY>>
Main: - <<EMPTY>>
Code: Select all
Procedure DebugString(s.s,*mem)
Protected i,b
If *mem
For i=0 To 39
b=PeekB(*mem+i)
s=s+Chr(b)+"'"+Hex(b&$FF)+"' "
Next i
Else
s+ " - <<EMPTY>>"
EndIf
Debug s
EndProcedure
Procedure.l Set_Integer(value.l)
If value <= $7F
*Integer=AllocateMemory(1)
PokeB(*Integer,value)
Else
*Integer=AllocateMemory(2)
PokeB(*Integer + 00,(value & $FF00) >> 8)
PokeB(*Integer + 01,value & $FF)
EndIf
ProcedureReturn *Integer
EndProcedure
Procedure.l Get_Integer(*Integer,free_memory.l)
value=0
For position=0 To MemorySize(*Integer) - 1
value.l=(x_value << 8) | PeekB(*Integer + position)
Next
If free_memory=#True
FreeMemory(*Integer)
EndIf
ProcedureReturn value
EndProcedure
Procedure.l BER_Encode(value.q)
*BER_Encode=#Null
;Debug -value
If value >= 0 And value < 128
*BER_Encode=AllocateMemory(1)
PokeB(*BER_Encode + 00,value)
ElseIf value >= 128 And value < 16384
*BER_Encode=AllocateMemory(2)
PokeB(*BER_Encode + 00,$80 |(value >> 7))
PokeB(*BER_Encode + 01,value & $7f)
ElseIf value >= 16384 And value < 2097152
*BER_Encode=AllocateMemory(3)
PokeB(*BER_Encode + 00,$80 |((value >> 14) & $7f))
PokeB(*BER_Encode + 01,$80 |((value >> 7) & $7f))
PokeB(*BER_Encode + 02,value & $7f)
ElseIf value >= 2097152 And value < 268435456
*BER_Encode=AllocateMemory(4)
PokeB(*BER_Encode + 00,$80 |((value >> 21) & $7f))
PokeB(*BER_Encode + 01,$80 |((value >> 14) & $7f))
PokeB(*BER_Encode + 02,$80 |((value >> 7) & $7f))
PokeB(*BER_Encode + 03,value & $7f)
ElseIf value >= 268435456 And value < 4294967296
*BER_Encode=AllocateMemory(5)
PokeB(*BER_Encode + 00,$80 |((value >> 28) & $0f))
PokeB(*BER_Encode + 01,$80 |((value >> 21) & $7f))
PokeB(*BER_Encode + 02,$80 |((value >> 14) & $7f))
PokeB(*BER_Encode + 03,$80 |((value >> 7) & $7f))
PokeB(*BER_Encode + 04,value & $7f)
EndIf
ProcedureReturn *BER_Encode
EndProcedure
Procedure.l BER_Decode_2(*input_data,cut.l,free_memory.l)
output_value.l=0
value_1.l=PeekB(*input_data+00)&$FF
value_2.l=PeekB(*input_data+01)&$FF
counter.l=2
If value_1=$80
output_value=$80
ElseIf value_1 > $80 And value_2 > $80
output_value=((value_1 - $80) << 7) +(value_2 - $80)
ElseIf value_1 > $80 And value_2 < $80
output_value=((value_1 - $80) << 7) + value_2
ElseIf value_1 < $80
output_value=value_1
counter=1
EndIf
If cut=#True
CopyMemory(*input_data + counter,*input_data,MemorySize(*input_data) - counter)
ReAllocateMemory(*input_data,MemorySize(*input_data) - counter)
EndIf
If free_memory=#True
FreeMemory(*input_data)
EndIf
ProcedureReturn output_value
EndProcedure
Procedure.l OID_Encode(oid_string.s)
dot_numbers=CountString(oid_string,".")
*OID_Encode=AllocateMemory(1024)
OID_Encode_Length=0
If Left(oid_string,1)="."
oid_string=Mid(oid_string,2,Len(oid_string) - 1)
EndIf
first=Val(StringField(oid_string,1,"."))
second=Val(StringField(oid_string,2,"."))
first=(first * 40) + second
*mem_value=BER_Encode(first)
CopyMemory(*mem_value,*OID_Encode,MemorySize(*mem_value))
OID_Encode_Length + MemorySize(*mem_value)
FreeMemory(*mem_value)
If CountString(oid_string,".") > 1
For position.l=3 To dot_numbers + 1
*mem_value=BER_Encode(Val(StringField(oid_string,position,".")))
CopyMemory(*mem_value,*OID_Encode + OID_Encode_Length,MemorySize(*mem_value))
OID_Encode_Length + MemorySize(*mem_value)
FreeMemory(*mem_value)
Next
EndIf
ReAllocateMemory(*OID_Encode,OID_Encode_Length)
ProcedureReturn *OID_Encode
EndProcedure
Procedure.s OID_Decode(*OID_Decode)
Dim OID.l(256)
OID_string.s=""
OID_count=1
subid=0
For counter=0 To MemorySize(*OID_Decode) - 1
value=PeekB(*OID_Decode + counter) & $FF
If subid & $FE000000
Debug "object too large"
EndIf
subid=(subid << 7) |(value & $7F)
If Not(value & $80)
OID(OID_count)=subid
OID_count + 1
subid=0
EndIf
Next
If OID(1)=43
OID(0)=1
OID(1)=3
ElseIf OID(1) < 64
OID(0)=0
ElseIf OID(1) < 128
OID(0)=1
OID(1)=64
Else
OID(0)=2
OID(1)=128
EndIf
For counter=0 To OID_count - 1
OID_string + "." + Str(OID(counter))
Next
ProcedureReturn OID_string
EndProcedure
Procedure.l Make_TLV(type.b,*input_data,free_memory.l)
Data_Length.l=MemorySize(*input_data )
*Octet_Length=Set_Integer(Data_Length )
Length.l=MemorySize(*Octet_Length)
*TLV=AllocateMemory(1 + Length + Data_Length)
PokeB(*TLV,type)
CopyMemory(*Octet_Length,*TLV + 1 ,Length)
CopyMemory(*input_data ,*TLV + 1 + Length,Data_Length)
FreeMemory(*Octet_Length)
If free_memory=#True
FreeMemory(*input_data)
EndIf
ProcedureReturn *TLV
EndProcedure
Procedure.l Make_TLV_Null(type.b)
*TLV=AllocateMemory(2)
PokeB(*TLV + 00,type)
PokeB(*TLV + 01,00 )
ProcedureReturn *TLV
EndProcedure
Procedure.l Join_Data(*memory_1,*memory_2,free_memory.l)
*Joined=AllocateMemory(MemorySize(*memory_1) + MemorySize(*memory_2))
CopyMemory(*memory_1,*Joined,MemorySize(*memory_1))
CopyMemory(*memory_2,*Joined + MemorySize(*memory_1),MemorySize(*memory_2))
If free_memory=#True
FreeMemory(*memory_1)
FreeMemory(*memory_2)
EndIf
ProcedureReturn *Joined
EndProcedure
Procedure.l Make_String(string.s)
*String=AllocateMemory(Len(string))
PokeS(*String,string)
ProcedureReturn *String
EndProcedure
Procedure.l Memory_Move_Left(*memory,offset.l)
If MemorySize(*memory) > offset
CopyMemory(*memory + offset,*memory,MemorySize(*memory) - offset)
ReAllocateMemory(*memory,MemorySize(*memory) - offset)
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Procedure.l Unpack_TLV(*input_data,cut_memory.l,free_memory.l)
*TMP=AllocateMemory(MemorySize(*input_data) - 1)
CopyMemory(*input_data + 1,*TMP,MemorySize(*TMP))
type.l=PeekB(*input_data) & $FF
return_value=#False
cut_length=0
If type=$05
cut_length=2
ElseIf type=$30 Or type > $9F
DebugString("TLV I: ",*TMP)
; SEQUENCE
sequence_length=BER_Decode_2(*TMP,#True,#False)
DebugString("TLV II: ",*TMP)
If sequence_length=MemorySize(*TMP)
return_value=*TMP
Else
Debug "ÖHA?"+Str(sequence_length)+" / "+Str(MemorySize(*tmp))
EndIf
Else
; Other
Length=PeekB(*TMP) & $FF
Memory_Move_Left(*TMP,1)
ReAllocateMemory(*TMP,Length)
return_value=*TMP
cut_length=2 + Length
EndIf
If cut_memory=#True
Memory_Move_Left(*input_data,cut_length)
DebugString("Cut: ",*input_data)
EndIf
If free_memory=#True
FreeMemory(*input_data)
EndIf
DebugString("Return: ",return_value)
ProcedureReturn return_value
EndProcedure
Procedure.l Make_SNMP_Packet(community_string.s,snmp_pdu.s,request_id.l,object_identifier.s)
return_value=#False
If UCase(snmp_pdu)="GET_NEXT"
SNMP_PDU_Type.l=$A1
*Value=Make_TLV_Null($05)
Else ; GET
SNMP_PDU_Type.l=$A0
*Value=Make_TLV_Null($05)
EndIf
; [ SNMP_Message [ Version_Number ] [ Community_String ] [ SNMP_PDU [ Request_ID ] [ Error ] [ Error_Index ] [ Varbind_List [ Varbind [ Object_Identifier ] [ Value ] ] ] ] ]
*OID=OID_Encode(object_identifier)
If *OID
*Object_Identifier=Make_TLV($06,*OID,#True)
EndIf
If *Object_Identifier And *Value
*Varbind_Data=Join_Data(*Object_Identifier,*Value,#True)
EndIf
If *Varbind_Data
*Varbind=Make_TLV($30,*Varbind_Data,#True)
EndIf
If *Varbind
*Varbind_List=Make_TLV($30,*Varbind,#True)
*Request_ID_Value=Set_Integer(request_id)
EndIf
If *Request_ID_Value And *Varbind_List
*Request_ID=Make_TLV($02,*Request_ID_Value,#True)
*Error_Value=Set_Integer($00)
EndIf
If *Request_ID And *Error_Value
*Error=Make_TLV($02,*Error_Value,#True)
*Error_Index_Value=Set_Integer($00)
EndIf
If *Error And *Error_Index_Value
*Error_Index=Make_TLV($02,*Error_Index_Value,#True)
*Temp_1=Join_Data(*Request_ID,*Error,#True)
EndIf
If *Error_Index And *Temp_1
*Temp_2=Join_Data(*Temp_1,*Error_Index,#True)
EndIf
If *Temp_2
*SNMP_PDU_Data=Join_Data(*Temp_2,*Varbind_List,#True)
EndIf
If *SNMP_PDU_Data
*SNMP_PDU=Make_TLV(SNMP_PDU_Type,*SNMP_PDU_Data,#True)
*SNMP_Community_String_Value=Make_String(community_string)
EndIf
If *SNMP_PDU And *SNMP_Community_String_Value
*SNMP_Community_String=Make_TLV($04,*SNMP_Community_String_Value,#True)
*SNMP_Version_Value=Set_Integer($00)
EndIf
If *SNMP_Community_String And *SNMP_Version_Value
*SNMP_Version=Make_TLV($02,*SNMP_Version_Value,#True)
EndIf
If *SNMP_Version
*Temp_3=Join_Data(*SNMP_Version,*SNMP_Community_String,#True)
EndIf
If *Temp_3
*SNMP_Message_Data=Join_Data(*Temp_3,*SNMP_PDU,#True)
EndIf
If *SNMP_Message_Data
*SNMP_Message=Make_TLV($30,*SNMP_Message_Data,#True)
return_value=*SNMP_Message
EndIf
ProcedureReturn return_value
EndProcedure
Procedure.l Unpack_SNMP_Response(*SNMP_Packet,request_id.l)
return_value=#False
DebugString("Unpack I: ",*snmp_packet)
*SNMP_Message=Unpack_TLV(*SNMP_Packet,#True,#False)
DebugString("Unpack II: ",*snmp_message)
If *SNMP_Message
*SNMP_Version=Unpack_TLV(*SNMP_Message,#True,#False)
If *SNMP_Version
*SNMP_Community=Unpack_TLV(*SNMP_Message,#True,#False)
If *SNMP_Community
SNMP_Version_Value.l=Get_Integer(*SNMP_Version,#True)
SNMP_Community_Value.s=PeekS(*SNMP_Community,MemorySize(*SNMP_Community))
FreeMemory(*SNMP_Community)
*SNMP_PDU=Unpack_TLV(*SNMP_Message,#True,#True)
If *SNMP_PDU
*Request_ID=Unpack_TLV(*SNMP_PDU,#True,#False)
*Error=Unpack_TLV(*SNMP_PDU,#True,#False)
*Error_Index=Unpack_TLV(*SNMP_PDU,#True,#False)
*Varbind_List=Unpack_TLV(*SNMP_PDU,#True,#True)
Request_ID=Get_Integer(*Request_ID,#True)
; Debug Request_ID
If *Varbind_List
*Varbind=Unpack_TLV(*Varbind_List,#True,#True)
return_value=*Varbind
EndIf
EndIf
EndIf
EndIf
EndIf
ProcedureReturn return_value
EndProcedure
Procedure.l SNMP_Send_And_Receive(ip_address.s,community.s,oid.s,type.s)
return_value.l=#False
If ip_address<>""
*ptr=sockinfo.sockaddr_in
sockinfo\sin_family=#AF_INET
sockinfo\sin_port=htons_(161)
sockinfo\sin_addr=inet_addr_(ip_address)
SockIdent=SOCKET_(#AF_INET,2,0) ;create socket (#SOCK_DGRAM for UDP)
If SockIdent=#INVALID_SOCKET
Debug "Socket cant be created!"
Else
; Debug "UDP socket created!"
RandomSeed(Random(99999))
Request_ID=Random(99999)
*packet=Make_SNMP_Packet(community,type,Request_ID,oid)
If *packet
packet_length=MemorySize(*packet)
send=sendto_(SockIdent,*packet,packet_length,0,*ptr,SizeOf(sockaddr_in))
If send<>#SOCKET_ERROR
*recv_buffer=AllocateMemory(512)
If *recv_buffer
recv_buffer_size=MemorySize(*recv_buffer)
; Debug recv_buffer_size
start=Date()
Repeat
Delay(1)
bytesRecv=recv_(SockIdent,*recv_buffer,recv_buffer_size,2)
If Date()-start>5
bytesRecv=#SOCKET_ERROR
Break
EndIf
Until bytesRecv<>-1
; Debug bytesRecv
DebugString("S&R I: ",*recv_buffer)
If bytesRecv<>#SOCKET_ERROR
ReAllocateMemory(*recv_buffer,bytesRecv)
*value=Unpack_SNMP_Response(*recv_buffer,Request_ID)
If *value
return_value=*value
EndIf
EndIf
DebugString("S&R II: ",*value)
FreeMemory(*recv_buffer)
EndIf
EndIf
FreeMemory(*packet)
EndIf
EndIf
EndIf
ProcedureReturn return_value
EndProcedure
Procedure.l Decode_Result(*result)
type=PeekB(*result + 00) & $FF
length=PeekB(*result + 01) & $FF
If type=$06
*oid=AllocateMemory(length)
CopyMemory(*result + 2,*oid,length)
oid_s.s=OID_Decode(*oid)
FreeMemory(*oid)
Debug oid_s
MessageRequester("OID S",oid_s)
Memory_Move_Left(*result,length + 2)
EndIf
type=PeekB(*result + 00) & $FF
length=PeekB(*result + 01) & $FF
If type=$04 And length > 0
*tmp=AllocateMemory(length)
CopyMemory(*result + 2,*tmp,length)
Debug PeekS(*tmp,length)
MessageRequester("Tpe 4",PeekS(*tmp,length))
EndIf
debugstring("Decode: ",*result)
FreeMemory(*result)
EndProcedure
Procedure ping(sIPAddress.s)
EchoMessage.s="Echo"
ResultSize.l=SizeOf(ICMP_ECHO_REPLY) + Len(EchoMessage)
*Result=AllocateMemory(ResultSize)
*Echo.ICMP_ECHO_REPLY=*Result
result=#False
If Len(sIPAddress) > 0
hFile.l=IcmpCreateFile_()
IPAddress.l=MakeIPAddress(Val(StringField(sIPAddress,1,".")),Val(StringField(sIPAddress,2,".")),Val(StringField(sIPAddress,3,".")),Val(StringField(sIPAddress+".",4,".")))
lngResult.l=IcmpSendEcho_(hFile,IPAddress,EchoMessage,Len(EchoMessage),0,*Result,ResultSize,500)
If lngResult
result=#True
; Debug ("Ping " + sIPAddress + " Octets: " + Str(*Echo\DataSize) + " Temps: " + Str(*Echo\RoundTripTime) + " ms TTL:" + StrU(*Echo\Options\Ttl,#Byte))
EndIf
IcmpCloseHandle_(hFile)
EndIf
FreeMemory(*Result)
ProcedureReturn result
EndProcedure
If InitNetwork()
IPAddress.s="172.16.222.222"
Debug IPAddress
If ping(IPAddress)
;MessageRequester("Ping",ipaddress+" successfull.")
Debug "PING OK"
*rec=SNMP_Send_And_Receive(IPAddress,"public","1.3.6.1.2.1.1.1.0","GET") ; or GET_NEXT
debugstring("Main: ",*rec)
If *rec
Debug "REC"
;MessageRequester("GET",PeekS(*rec))
Decode_Result(*rec)
EndIf
EndIf
Debug "------------------"
EndIf
- Michael Vogel
- Addict
- Posts: 2807
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Still being confused - Peters code is a really great program, but hard to understand (for me) in all details.
As posted before, with this code I do not get any output on the components around me (3Com, Cisco, Foundry).
Tools like Getif&Co show me correct results and also the received packets from peters code are perfect, but there must be a (small) hole in decoding...
So I tried to understand the ASN.1 structure and wrote some lines for decoding a catched packet:
Now I'm able to get (most) of the records, but I have no idea, when to stop and which records can be ignored and which one is the result. In this case its the field #12, I know - but will that be the same independently which SNMP message will have to be decoded?
And where is the difference to peters code which does not show me any results (see posting above)?
Any ideas?
Thanks,
Michael
As posted before, with this code I do not get any output on the components around me (3Com, Cisco, Foundry).
Tools like Getif&Co show me correct results and also the received packets from peters code are perfect, but there must be a (small) hole in decoding...
So I tried to understand the ASN.1 structure and wrote some lines for decoding a catched packet:
Code: Select all
Packet.s="30 82 00 4A 02 01 00 04 06 70 75 62 6C 69 63 A2 82 00 3B 02 02 C7 2B 02 01 00 02 01 00 30 82 00 2D 30 82 00 29 06 08 2B 06 01 02 01 01 01 00 04 1D 42 72 6F 61 64 62 61 6E 64 20 52 65 73 69 64 65 6E 74 69 61 6C 20 47 61 74 65 77 61 79 "
Global FrameLength=Len(Packet.s)/3
Global FrameData.s=Space(FrameLength)
For i=0 To FrameLength-1
PokeB(@FrameData+i,Val("$"+Mid(Packet,i*3+1,2)))
Next i
Procedure DebugString(s.s,*mem)
Protected i,b
If *mem
For i=0 To 39
b=PeekB(*mem+i)&$ff
If b>31
s=s+Hex(b&$FF)+"|"+Chr(b)+" "
Else
s=s+RSet(Hex(b),2,"0")+"|. "
EndIf
Next i
Else
s+ " - <<EMPTY>>"
EndIf
Debug s
EndProcedure
Structure Reference
value.l
EndStructure
Procedure.l BER_Length(*memory,*pos.Reference)
Protected byte
Protected length
Protected n
byte=PeekB(*memory+*pos\Value)
*pos\Value+1
If byte&$80; multi-byte length
byte&$3; number of bytes For length information
While byte
length<<8
length+(PeekB(*memory+*pos\Value)&$ff)
byte-1
*pos\Value+1
Wend
Else
length=byte&$7f
EndIf
;Debug "Len: "+Str(length)
ProcedureReturn length
EndProcedure
Procedure.l BER_Integer(*memory,length)
Protected n
While length
n<<8
n+(PeekB(*memory)&$ff)
length-1
*memory+1
Wend
ProcedureReturn n
EndProcedure
Procedure.s BER_Object(*memory,length)
Protected byte
Protected OID.s
While length
byte=PeekB(*memory)&$ff
If byte='+'
OID="1.3"
Else
OID+"."+Chr('0'+PeekB(*memory))
EndIf
*memory+1
length-1
Wend
ProcedureReturn OID
EndProcedure
Procedure.l BER_Class(*memory)
Protected byte
Protected length
Protected pos
; Class (Bits 7/8)
; 0 - Universal (integer, string etc.)
; 1 - Application (IP address)
; 2 - Context (complex data)
; 3 - Private (non standard data)
; Data Type (Bit 6)
; 0 - primitive data-type
; 1 - constucted data-type
; ASN.1 Type (Bit 5)
; 0 - no
; 1 - yes
pos=0
For i=1 To 12
byte=PeekB(*memory+pos)&$ff
Debug "----------"
Debug "Pos: "+Str(pos)+" (=$"+Hex(byte&$ff)+")"
pos+1
Select byte>>6; class...
Case 0; universal class
If byte&$20; constructed data type
If byte&$10; ASN.1
length=BER_Length(*memory,@pos);
EndIf
Else; primitive data type
length=BER_Length(*memory,@pos);
Select byte&$f
Case 2
Debug "integer: "+Str(BER_Integer(*memory+pos,length))
Case 3
Debug "bit string"
Case 4
Debug "octet string: "+PeekS(*memory+pos,length)
Case 5
Debug "null"
Case 6
Debug "object: "+BER_Object(*memory+pos,length)
EndSelect
pos+length
EndIf
Case 2; context specific
Debug "SNMP"
If byte&$20; constructed data type
length=BER_Length(*memory,@pos);
Debug "S:"+Str(length)
Else; primitive data type
Debug "?"
EndIf
EndSelect
Next i
EndProcedure
DebugString("Init:",@FrameData)
BER_Class(@FrameData)
And where is the difference to peters code which does not show me any results (see posting above)?
Any ideas?
Thanks,
Michael
- Michael Vogel
- Addict
- Posts: 2807
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Got it
It's not as fine as peters original code, but should work...
Also threading is not a problem and all results are kept in a structure (SNMP)...
Beside some missing actions (convert tick value into string, check for additional data types) there is one unsolved issue: some strings (MAX addresses) should be converted by using a hex function, but i see no difference in the SNMP response packet to other (octet) strings...

It's not as fine as peters original code, but should work...
Also threading is not a problem and all results are kept in a structure (SNMP)...
Beside some missing actions (convert tick value into string, check for additional data types) there is one unsolved issue: some strings (MAX addresses) should be converted by using a hex function, but i see no difference in the SNMP response packet to other (octet) strings...
Code: Select all
; Define
EnableExplicit
; Alive state
Enumeration
#Station_Unknown
#Station_Down
#Station_Up
EndEnumeration
; GetType
Enumeration $A0
#GET
#GET_NEXT
EndEnumeration
; Status
Enumeration
#SNMP_Unknown
#SNMP_Ok
#SNMP_Sent
#SNMP_Received
#SNMP_Error
#SNMP_Error_OID
#SNMP_Error_RID
#SNMP_Error_Name
EndEnumeration
;ValueType
Enumeration
#TypeUnknown
#TypeInteger
#TypeString
#TypeIP
#TypeTicks
#TypeObject
EndEnumeration
; internally used
Enumeration
#Field_Header
#Field_Version
#Field_Community
#Field_PDU
#Field_RequestID
#Field_ErrorState
#Field_ErrorIndex
#Field_VariableLengthWithHeader
#Field_VariableLengthWithoutHeader
#Field_OID
#Field_Variable
#Field_Nil
EndEnumeration
#SNMP_MaxPacketSize=548
Structure Reference
value.l
EndStructure
Structure StationType
IP.l
Community.s
Alive.w
EndStructure
Structure SNMPType
StationNumber.w
GetType.w
RequestID.w
OID.s
ResponseOID.s
ValueType.w
Value.s
Status.w
EndStructure
Global MaxStations=50
Global MaxRequests=100
Global Dim Station.StationType(MaxStations)
Global Dim SNMP.SNMPType(MaxRequests)
Global RequestID.w
; EndDefine
Procedure.l BE_Length(*memory,*pos.Reference)
; Calculates length of actual field...
Protected byte
Protected length
Protected n
byte=PeekB(*memory+*pos\Value)
*pos\Value+1
If byte&$80; multi-byte length
byte&$3; number of bytes for length information
While byte
length<<8
length+(PeekB(*memory+*pos\Value)&$ff)
byte-1
*pos\Value+1
Wend
Else
length=byte&$7f
EndIf
;Debug "Len: "+Str(length)
ProcedureReturn length
EndProcedure
Procedure.l BE_Integer(*memory,length)
; Encodes memory to integer value...
Protected n
While length
n<<8
n+(PeekB(*memory)&$ff)
length-1
*memory+1
Wend
ProcedureReturn n
EndProcedure
Procedure.s BE_Object(*memory,length)
; Encodes Memory to OID string...
Protected ID
Protected OID.s
Protected byte
Protected i=0
While i<length
byte=PeekB(*memory+i)&$FF
If ID & $FE000000
OID+".???"
Break
EndIf
ID<<7
ID|(byte&$7F)
If byte&$80=0
If i
OID+"."+Str(ID)
Else
Select byte
Case 43
OID=".1.3"
Case 0 To 63
OID=".0"
Case 64 To 127
OID=".1.64"
Default
OID=".2.128"
EndSelect
EndIf
ID=0
EndIf
i+1
Wend
ProcedureReturn OID
EndProcedure
Procedure.l BM_Integer(value.l,*memory,*pos.Reference)
; Writes integer value into memory, starting at position *pos
; Returns number of used Bytes...
If (value<$80)
PokeB(*memory+*pos\Value,value)
value=1
Else
PokeB(*memory+*pos\Value,(value>>8)&$ff)
PokeB(*memory+*pos\Value+1,value&$ff)
value=2
EndIf
*pos\Value+value
ProcedureReturn value
EndProcedure
Procedure.l BM_Value(value.l,*memory,*pos.Reference)
; should use quads, but because of pures poor quad handling limited to long for now ;(
; Writes integer value into memory, starting at position *pos
; Returns number of used Bytes...
If (value>=0) And (value<128)
PokeB(*memory+*pos\Value,value)
value=1
ElseIf (value>=128) And (value<16384)
Debug Str(value)+" = "+Str($80|(value>>7))+", "+Str(value&$7f)
PokeB(*memory+*pos\Value, $80|(value>>7))
PokeB(*memory+*pos\Value+1, value&$7f)
value=2
ElseIf (value>=16384) And (value<2097152)
PokeB(*memory+*pos\Value, $80|((value>>14)&$7f))
PokeB(*memory+*pos\Value+1, $80|((value>>7)&$7f))
PokeB(*memory+*pos\Value+2, value&$7f)
value=3
ElseIf (value>=2097152) And (value<268435456)
PokeB(*memory+*pos\Value, $80|((value>>21)&$7f))
PokeB(*memory+*pos\Value+1, $80|((value>>14)&$7f))
PokeB(*memory+*pos\Value+2, $80|((value>>7)&$7f))
PokeB(*memory+*pos\Value+3, value&$7f)
value=4
ElseIf (value>=268435456) And (value<4294967296)
PokeB(*memory+*pos\Value, $80|((value>>28)&$7f))
PokeB(*memory+*pos\Value+1, $80|((value>>21)&$7f))
PokeB(*memory+*pos\Value+2, $80|((value>>14)&$7f))
PokeB(*memory+*pos\Value+3, $80|((value>>7)&$7f))
PokeB(*memory+*pos\Value+4, value&$7f)
value=5
Else
value=0
EndIf
*pos\Value+value
ProcedureReturn value
EndProcedure
Procedure.l BM_String(value.s,*memory,*pos.Reference)
; Writes string value into memory, starting at position *pos
; Returns number of used Bytes...
Protected length=Len(value)
If length
PokeS(*memory+*pos\Value,value,length)
*pos\Value+length
EndIf
ProcedureReturn length
EndProcedure
Procedure.l BM_Object(OID.s,*memory,*pos.Reference)
; Writes OID object into memory starting at position *pos
; Returns number of used bytes
Protected value
Protected i,n
Protected length=0
If PeekB(@OID)='.'
OID=PeekS(@OID+1)
EndIf
n=CountString(OID,".")
value=Val(StringField(OID,1,".")) *40 + Val(StringField(OID,2,"."))
length+BM_Value(value,*memory,*pos)
If CountString(OID,".") > 1
For i=3 To n+1
length+BM_Value(Val(StringField(OID,i,".")),*memory,*pos)
Next
EndIf
ProcedureReturn length
EndProcedure
Procedure.l BM_Move(value.l,length.l,*memory,*pos.Reference)
; Insert byte value into memory block...
; Returns total length
CopyMemory(*memory+*pos\Value-length,*memory+*pos\Value-length+2,length)
PokeB(*memory+*pos\Value-length,value)
PokeB(*memory+*pos\Value-length+1,length)
*pos\Value+2
ProcedureReturn length+2
EndProcedure
Procedure.l BM_Null(value.l,*memory,*pos.Reference)
; Writes byte value into memory address...
; Returns length (=2)
PokeB(*memory+*pos\Value,value)
PokeB(*memory+*pos\Value+1,0)
*pos\Value+2
ProcedureReturn 2
EndProcedure
Procedure.l Ping(n)
; Pings Station(n)\IP...
; Returns #True if a reply packet is seen from the station
Protected EchoMessage.s
Protected EchoSize
Protected *Echo.ICMP_ECHO_REPLY
Protected *EchoResult
Protected Handle
With Station(n)
\Alive=#Station_Down
EchoMessage.s="Michael Vogel"
EchoSize.l=SizeOf(ICMP_ECHO_REPLY)+Len(EchoMessage)
*EchoResult=AllocateMemory(EchoSize)
*Echo=*EchoResult
If \IP
Handle=IcmpCreateFile_()
If IcmpSendEcho_(Handle,\IP,EchoMessage,Len(EchoMessage),0,*EchoResult,EchoSize,500)
; Received an ICMP-Response...
If PeekL(*EchoResult)=\IP
;...from the destination address (otherwise it will be a destination unreachable message from the default gateway)
\Alive=#Station_Up
EndIf
EndIf
IcmpCloseHandle_(Handle)
EndIf
FreeMemory(*EchoResult)
ProcedureReturn \Alive
EndWith
EndProcedure
Procedure.l PDU_Check(n,*memory)
Protected byte
Protected length
Protected pos
Protected field
Protected Value.s
; Class (Bits 7/8)
; 0 - Universal (integer, string etc.)
; 1 - Application (IP address, Time Ticks)
; 2 - Context (complex data)
; 3 - Private (non standard data)
; Data Type (Bit 6)
; 0 - primitive data-type
; 1 - constructed data-type
; ASN.1 Type (Bit 5)
; 0 - no
; 1 - yes
With SNMP(n)
pos=0
Repeat
byte=PeekB(*memory+pos)&$ff
;Debug "Field: "+Str(field)+" Pos: "+Str(pos)+" (=$"+Hex(byte&$ff)+")"
pos+1
length=BE_Length(*memory,@pos);
Select byte>>6; class...
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Case 0; universal class
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If byte&$20; constructed data type
If byte&$10; ASN.1
;Debug " Length: "+Str(length)
EndIf
Else; primitive data type
Select byte&$f
Case 2
\ValueType=#TypeInteger
Value=Str(BE_Integer(*memory+pos,length))
;Debug " integer: "+Value
Case 3
;Debug " bit string"
Case 4
\ValueType=#TypeString
Value=PeekS(*memory+pos,length)
;Debug " octet string: "+Value
Case 5
;Debug " null"
Case 6
\ValueType=#TypeObject
Value=BE_Object(*memory+pos,length)
;Debug " object: "+Value
Default
Debug Str(n)+" UNKNOWN TYPE: "+Str(byte)
EndSelect
pos+length
EndIf
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Case 1; application
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If byte&$20=0; primitive data type
Select byte&$f
Case 3; ticks
Value=Str(BE_Integer(*memory+pos,length))
\ValueType=#TypeTicks
EndSelect
EndIf
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Case 2; context specific
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If byte&$20; constructed data type
If byte=$A2
; $A2 GetResponse PDU...
EndIf
Else; primitive data type
Debug Str(n)+" ERROR: Unknown Packet"
\Status=#SNMP_Error
field=#Field_Nil
EndIf
EndSelect
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Select field
Case #Field_ErrorState
If Val(Value)
\Status=#SNMP_Error_Name
Debug \Status
Debug Str(n)+" NAME ERROR: "+Value
field=#Field_Nil
EndIf
Case #Field_RequestID
If Val(Value)<>\RequestID
\Status=#SNMP_Error_RID
Debug Str(n)+" RID ERROR: "+Value+"~"+Value
field=#Field_Nil
EndIf
Case #Field_OID
\ResponseOID=Value
If (\GetType=#Get) And (Value<>\OID)
\Status=#SNMP_Error_OID
Debug Str(n)+" OID ERROR: "+Value+"~"+\OID
field=#Field_Nil
EndIf
Case #Field_Variable
SNMP(n)\Value=Value
\Status=#SNMP_Ok
EndSelect
field+1
Until field>#Field_Variable
ProcedureReturn \Status
EndWith
EndProcedure
Procedure.l PDU_Make(n,*memory)
; compose SNMP packet into reserved memory (548 bytes)
; n = Request number
; Returns packet length
Protected length
Protected pos
Protected PositionA,PositionB
With SNMP(n)
RequestID+1;Random(65535)
\RequestID=RequestID
If \GetType<>#GET_NEXT : \GetType=#GET : EndIf
; SNMPv1
length=BM_Value($00,*memory,@pos)
length=BM_Move($02,length,*memory,@pos)
; Community
length=BM_String(Station(\StationNumber)\Community,*memory,@pos)
length=BM_Move($04,length,*memory,@pos)
PositionA=pos
; Request ID
length=BM_Integer(\RequestID,*memory,@pos)
length=BM_Move($02,length,*memory,@pos)
; Error-Status
length=BM_Value(0,*memory,@pos)
length=BM_Move($02,length,*memory,@pos)
; Error-Index
length=BM_Value(0,*memory,@pos)
length=BM_Move($02,length,*memory,@pos)
PositionB=pos
; OID
length=BM_Object(\OID,*memory,@pos)
\OID=BE_Object(*memory+PositionB,length); put normalized OID into database
length=BM_Move($06,length,*memory,@pos)
; NULL
length=BM_Null($05,*memory,@pos)
; Envelope OID and Null-field (two times)
length=BM_Move($30,pos-PositionB,*memory,@pos)
length=BM_Move($30,pos-PositionB,*memory,@pos)
; Envelope Request-ID, Error Information and OID-Envelope
length=BM_Move(\GetType,pos-PositionA,*memory,@pos)
; Envelope all SNMP fields
length=BM_Move($30,pos,*memory,@pos)
EndWith
ProcedureReturn pos
EndProcedure
Procedure.l SNMP_Get(n)
Protected *pointer
Protected *Buffer
Protected Status
Protected Start
Protected SockInfo.sockaddr_in
Protected SockIdent
With SNMP(n)
\Value=""
\ValueType=#TypeUnknown
\Status=#SNMP_Unknown
If Station(\StationNumber)\IP
*pointer=Sockinfo
sockinfo\sin_family=#AF_INET
sockinfo\sin_port=htons_(161)
sockinfo\sin_addr=Station(\StationNumber)\IP
SockIdent=SOCKET_(#AF_INET,2,0)
If SockIdent<>#INVALID_SOCKET
*Buffer=AllocateMemory(#SNMP_MaxPacketSize)
If *Buffer
Status=PDU_Make(n,*Buffer)
If Status
If sendto_(SockIdent,*Buffer,Status,0,*pointer,SizeOf(sockaddr_in)) <> #SOCKET_ERROR
;Status=0
Start=Date()
Repeat
Delay(1)
Status=recv_(SockIdent,*Buffer,#SNMP_MaxPacketSize,2)
If Date()-Start>5
Status=#SOCKET_ERROR
EndIf
Until Status<>0
If Status<>#SOCKET_ERROR
;ReAllocateMemory(*Buffer,Status)
Status=PDU_Check(n,*Buffer)
\Status=Status
Else
Status=0
\Status=#SNMP_Error
EndIf
EndIf
EndIf
FreeMemory(*Buffer)
EndIf
EndIf
EndIf
EndWith
ProcedureReturn Status
EndProcedure
Procedure Main()
If InitNetwork()
Station(0)\IP=inet_addr_("172.16.222.222")
Station(0)\Community="public"
; *** just for testing ***
Protected i
For i=1 To 7
SNMP(i)\StationNumber=0
SNMP(i)\OID="1.3.6.1.2.1.1."+Str(i)+".0"
SNMP(i)\Gettype=#GET
Next i
For i=1 To 7
SNMP(i+7)\StationNumber=0
SNMP(i+7)\OID=".1.3.6.1.2.1.2.2.1."+Str(i)+".1"
SNMP(i+7)\Gettype=#GET
Next i
If Ping(0)=#Station_Up
; *** brute force, have to be modified ***
For i=1 To 14
CreateThread(@SNMP_Get(),i)
Next i
Delay(2000) ;)
Protected Look.s
For i=1 To 14
Look+"[ "+Str(i)+":"+Str(SNMP(i)\Status)+","+Str(SNMP(i)\ValueType)+" ] "+SNMP(i)\Value+#CR$
Debug "~~~ "+Str(i)+" ~~~"
Debug Str(SNMP(i)\Status)+" / "+Str(SNMP(i)\ValueType)+" / "+SNMP(i)\ResponseOID
Debug SNMP(i)\Value
Next i
MessageRequester("Results",Look)
EndIf
EndIf
EndProcedure
Main()
Bringing up something old (and assuming herr Vogel is still around
) did you fix the issue with hex vs. octal?

( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
( The path to enlightenment and the PureBasic Survival Guide right here... )