Snmp Get
Posted: Wed Nov 02, 2005 4:34 pm
Anybody has information how to implement this function in PureBasic ?
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 ?
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?
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
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
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)
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()