ich hab mir mal das SNMP Protokoll mal bissel reingezogen und was für Purebasic geschrieben. Der Programmteil fragt mit der SNMP Version 1 die Daten vom Gerät ab. Version 2 und 3 hab ich noch nicht drinne... muss mal schauen wie dort das dann alles verschluesselt ist...
Auf jedenfall funktioniert es erstmal. Man braucht aber die Userlib UDPNetwork (http://www.Purearea.net) da das SNMP Protokoll auf dem UDP Protokoll laeuft.
Manche Teile wie z.b. "Bit String" abfragen ist nicht drinne da ich keine Information habe wie der Wert zurückgesendet wird.
Wenn Fehler drinnen sein sollten dann sagt mir bescheid...
Code: Alles auswählen
; German forum:
; Author: Torakas (M. Kuhn)
; Date: 14. Juni 2005
; SNMP Modul - Version 1.01 by Torakas
; Dieser Code ist frei verfügbar. Weiter entwicklung ist erwünscht, der Code muss aber auch in den folgenden Version
; frei zugänglich sein. Versionshistory mit Authoren muss erhalten bleiben.
; Aufruf ReadSNMP(Struktur.OID, IP Adresse des Gerätes)
; Vor dem Aufruf muss in der Struktur die OID und der lese Mode gesetzt werden (get / getnext)
; Mit getnext kann man sich ein Walk auch selber basteln. Andere Programme machen das nicht anderster
; ****** Hinweis: Es wird die UserLib "UDPNetwork" von "Sebastian 'PureFan' Lackner" verwendet. Diese kann man auf
; der Webseite www.Purearea.net finden.
Structure OID
oldOID.s
newOID.s
Datatype.b ; 1 = Boolean; 2 = Integer; 3 = Bitstring; 4 = Octet String; 5 = Null type; 6 = OID; 7 = Real type
; 8 = Enumerated type; 9 = Sequence and sequence-of types; 40 = IpAddress; 41 = Counter (Counter32 in SNMPv2)
; 42 = Gauge (Gauge32 in SNMPv 2); 43 = TimeTicks; 44 = Opaque; 45 = NsapAddress; 46 = Counter64 (available only in SNMPv2)
; 47 = Uinteger32 (available only in SNMPv2)
Returnvalue.s
ErrorStatus.b ; ErrorStatus: Dient zur Signalisierung eines Fehlers nach einem Request. Mögliche Werte sind: noError (0), tooBig(1), noSuchName(2), badValue(3), readOnly(4), genErr(5).
ErrorIndex.b ; Error Index: Falls dieser Wert nicht Null ist, beinhaltet dieser einen Zeiger auf einen Wert im VariableBindings Feld, der fehlerhaft ist.
mode.b ; 1 = get; 2 = getnext
EndStructure
Declare HexVal(a$)
Declare.b ReadSNMP(*SNMPValues.OID, IPAdress.s)
DefType.OID SNMPValue
SNMPValue\newOID = "1.3.6.1.2.1.1.1.0"
SNMPValue\mode = 1 ; get
ReadSNMP(@SNMPValue, "192.168.0.3")
Debug SNMPValue\oldOID
Debug SNMPValue\newOID
Debug SNMPValue\Datatype
Debug SNMPValue\Returnvalue
Debug SNMPValue\ErrorStatus
Debug SNMPValue\ErrorIndex
End
Procedure.b ReadSNMP(*SNMPValues.OID, IPAdress.s)
*SNMPValues\oldOID = ""
*SNMPValues\Datatype = 0
*SNMPValues\Returnvalue = ""
*SNMPValues\ErrorStatus = 0
*SNMPValues\ErrorIndex = 0
If UDPInitNetwork() And UDPConnectServer(161,IPAdress.s, MyOID.UDPConnect)
OID.s = *SNMPValues\newOID
addchars.l = 0
anzpoints.l = CountString(OID.s, ".")
For i = 3 To anzpoints.l + 1
If Val(StringField(OID.s, i, ".")) >= 128
addchars.l + 1
EndIf
Next i
pointer.l = 0
*Buffer = AllocateMemory(1024)
; Erstelle UDP Header
PokeB(*Buffer + pointer.l, 48) : pointer + 1 ; Hex 30 (Sequenz of)
PokeS(*Buffer + pointer.l, Chr(32 + (CountString(OID.s, ".") + addchars.l)), 1) : pointer + 1 ; Gesamtlänge des Headers
PokeB(*Buffer + pointer.l, 02) : pointer + 1 ; Integer
PokeB(*Buffer + pointer.l, 01) : pointer + 1 ; Länge 1
PokeB(*Buffer + pointer.l, 00) : pointer + 1 ; Wert 0 (Version 1)
PokeB(*Buffer + pointer.l, 04) : pointer + 1 ; Octet String
PokeB(*Buffer + pointer.l, 06) : pointer + 1 ; Länge 6
PokeB(*Buffer + pointer.l, 112) : pointer + 1 ; P
PokeB(*Buffer + pointer.l, 117) : pointer + 1 ; u
PokeB(*Buffer + pointer.l, 98) : pointer + 1 ; b
PokeB(*Buffer + pointer.l, 108) : pointer + 1 ; l
PokeB(*Buffer + pointer.l, 105) : pointer + 1 ; i
PokeB(*Buffer + pointer.l, 99) : pointer + 1 ; c
If *SNMPValues\mode = 1
PokeS(*Buffer + pointer.l, Chr(160), 1) : pointer + 1 ; A0 - GetRequest-PDU
ElseIf *SNMPValues\mode = 2
PokeS(*Buffer + pointer.l, Chr(161), 1) : pointer + 1 ; A1 - GetNextRequest-PDU
Else
ProcedureReturn #False ; Vergessen die Angabe zu machen welche Art abgerufen werden soll
EndIf
PokeS(*Buffer + pointer.l, Chr(19 + (CountString(OID.s, ".") + addchars.l)), 1) : pointer + 1 ; Länge
PokeB(*Buffer + pointer.l, 02) : pointer + 1 ; Integer
PokeB(*Buffer + pointer.l, 03) : pointer + 1 ; Länge 3
RandomSeed(Date())
SRequestID.l = Random(65536) ; Maximum RequestID 65536
Requeststr.s = Hex(SRequestID.l)
Requeststr.s = RSet(Requeststr.s, 6, "0") ; 000000
For i = 0 To 2
PokeS(*Buffer + pointer.l, Chr(HexVal(Mid(Requeststr.s, 1 + (i * 2), 2))) ) : pointer.l + 1 ; RequestID in 3 Bytes schreiben
Next i
PokeB(*Buffer + pointer.l, 02) : pointer + 1 ; Integer
PokeB(*Buffer + pointer.l, 01) : pointer + 1 ; Länge 1
PokeB(*Buffer + pointer.l, 00) : pointer + 1 ; ErrorStatus
PokeB(*Buffer + pointer.l, 02) : pointer + 1 ; Integer
PokeB(*Buffer + pointer.l, 01) : pointer + 1 ; Länge 1
PokeB(*Buffer + pointer.l, 00) : pointer + 1 ; ErrorIndex
PokeB(*Buffer + pointer.l, 48) : pointer + 1 ; Hex 30 (Sequenz of)
PokeS(*Buffer + pointer.l, Chr(6 + (CountString(OID.s, ".") + addchars.l)), 1) : pointer + 1 ; Länge (VarBindList)
PokeB(*Buffer + pointer.l, 48) : pointer + 1 ; Hex 30 (Sequenz of)
PokeS(*Buffer + pointer.l, Chr(4 + (CountString(OID.s, ".") + addchars.l)), 1) : pointer + 1 ; Länge (VarBind)
PokeB(*Buffer + pointer.l, 06) : pointer + 1 ; OBJECT ID
PokeB(*Buffer + pointer.l, (CountString(OID.s, ".") + addchars.l)) : pointer + 1 ; Länge der OID - die ersten beiden stellen
anzpoints.l = CountString(OID.s, ".")
For i = 1 To anzpoints.l + 1
If i = 1
tmpval.l = Val(StringField(OID.s, 1, ".")) * 40 ; erste oid immer x40
tmpval.l + Val(StringField(OID.s, 2, "."))
i = 2
Else
tmpval.l = Val(StringField(OID.s, i, "."))
EndIf
If i >= 3 And tmpval.l >= 128
PokeS(*Buffer + pointer.l, Chr(129)) : pointer + 1 ; Da tmpvar >= 128 ist wird es in zwei Byte geschrieben
tmpval.l - 128
EndIf
PokeS(*Buffer + pointer.l, Chr(tmpval.l)) : pointer + 1 ; oid in Hexform schreiben (erste zwei zeichen zusammengefasst)
Next i
PokeB(*Buffer + pointer.l, 05) : pointer + 1 ; NULL
PokeB(*Buffer + pointer.l, 00) : pointer + 1 ; 0
UDPSend(MyOID, *Buffer, pointer)
*SNMPValues\oldOID = *SNMPValues\newOID
*SNMPValues\newOID = ""
UDPStartCaptureEvents(MyOID.UDPConnect)
;UDPDataAvailable(MyOID.UDPConnect)
TimeOut.b = 0
*receiveBuffer = AllocateMemory(4096)
Repeat
BytesReceived = UDPReceive(MyOID.UDPConnect, *receiveBuffer, 4096)
Delay(1)
TimeOut + 1
Until BytesReceived > 0 Or TimeOut > 50
paketlen.l = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + 1, 1))), 2, "0")) ; Lese am zweiten Byte wie lang das ganze SNMP Paket ist.
readpointer.l = 16
RequestIDLaenge.b = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0"))
RequestIDString.s = ""
For i = (readpointer + 1) To readpointer + RequestIDLaenge.b
RequestIDString.s + RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")
Next i
RRequestID.l = HexVal(RequestIDString.s)
readpointer.l + (RequestIDLaenge.b + 1)
If SRequestID.l = RRequestID.l ; Nur wenn die zwei RequestID´s zusammenpassen wird weitergelesen
; ErrorStatus auslesen
*SNMPValues\ErrorStatus = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + (readpointer.l + 2), 1))), 2, "0"))
readpointer.l + 3
; ErrorIndex auslesen
*SNMPValues\ErrorIndex = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + (readpointer.l + 2), 1))), 2, "0"))
readpointer.l + 7
If HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) = 6 ; Es muss ein Object ID kommen
readpointer.l + 1
OIDRLen.b = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) ; Lese die Laenge des OID´s ein
For i = (readpointer + 1) To readpointer + OIDRLen.b
If i = (readpointer + 1) ; erstes Zeichen
OIDStr.s = Str(Round(HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")) / 40, 0)) + "." ; Erstes Zeichen. Dezimal durch 40.
OIDStr.s + Str(HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")) % 40) ; Restwert ist zweites Zeichen der OID
Continue
Else
OIDStr.s + "."
EndIf
If HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")) = 129
i + 1
OIDStr.s + Str(HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")) + 128)
Continue
EndIf
OIDStr.s + Str(HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")))
Next i
*SNMPValues\newOID = OIDStr.s
readpointer.l + (OIDRLen.b + 1)
RType.l = 0
RType.l = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")) ; Was fuer ein Rückgabetyp kommt jetzt...
If RType.l = 02 ; Hex 02 - Integer
readpointer.l + 1
IntegerLen.b = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) ; Lese die Laenge des Gauge´s ein
For i = (readpointer + 1) To readpointer + IntegerLen.b
IntegerString.s + RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")
Next i
*SNMPValues\Returnvalue = Str(HexVal(IntegerString.s)) ; Lese die Laenge des OID´s ein
EndIf
If RType.l = 03 ; Hex 03 - BIT STRING
; Keine Information wie das aussieht im Paket
EndIf
If RType.l = 04 ; Hex 04 - OCTET STRING
readpointer.l + 1
OctetStringLen.l = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) ; Lese die Laenge des Octet Strings´s ein
readpointer.l + 1
*SNMPValues\Returnvalue = PeekS(*receiveBuffer + readpointer, OctetStringLen.l)
EndIf
If RType.l = 05 ; Hex 05 - NULL
; dummy
EndIf
If RType.l = 06 ; Hex 06 - OBJECT IDENTIFIER
readpointer.l + 1
OIDRLen.b = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) ; Lese die Laenge des OID´s ein
For i = (readpointer + 1) To readpointer + OIDRLen.b
If i = (readpointer + 1) ; erstes Zeichen
OIDStr.s = Str(Round(HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")) / 40, 0)) + "." ; Erstes Zeichen. Dezimal durch 40.
OIDStr.s + Str(HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")) % 40) ; Restwert ist zweites Zeichen der OID
Continue
Else
OIDStr.s + "."
EndIf
; Keine information ob die Regelung wenn wert über 128 ist in zwei Bytes geteilt wird. Hab es mal drinne gelassen
If HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")) = 129
i + 1
OIDStr.s + Str(HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")) + 128)
Continue
EndIf
ValueOID.s + Str(HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")))
Next i
*SNMPValues\Returnvalue = ValueOID.s
EndIf
If RType.l = 64 ; Hex 40 - IPAdress
readpointer.l + 1
IPAdressLen.b = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) ; Laenge der IPAdress
ValueIPAdress.s = ""
For i = (readpointer + 1) To readpointer + OIDRLen.b
If i > (readpointer + 1)
ValueIPAdress.s + "."
EndIf
ValueIPAdress.s + Str(HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")))
Next i
EndIf
If RType.l = 65 ; Hex 41 - Counter (Counter32 in SNMPv2)
readpointer.l + 1
CounterLen.b = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) ; Lese die Laenge des Gauge´s ein
For i = (readpointer + 1) To readpointer + CounterLen.b
CounterString.s + RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")
Next i
*SNMPValues\Returnvalue = Str(HexVal(CounterString.s))
EndIf
If RType.l = 66 ; Hex 42 - Gauge (Gauge32 in SNMPv 2)
readpointer.l + 1
GaugeLen.b = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) ; Lese die Laenge des Gauge´s ein
For i = (readpointer + 1) To readpointer + GaugeLen.b
GaugeString.s + RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")
Next i
*SNMPValues\Returnvalue = Str(HexVal(GaugeString.s))
EndIf
If RType.l = 67 ; Hex 43 - TimeTicks
readpointer.l + 1
TimeTicksLen.b = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) ; Lese die Laenge des Gauge´s ein
For i = (readpointer + 1) To readpointer + TimeTicksLen.b
TimeTicksString.s + RSet(Hex(Asc(PeekS(*receiveBuffer + i, 1))), 2, "0")
Next i
*SNMPValues\Returnvalue = Str(HexVal(TimeTicksString.s)) ; Lese die Laenge des OID´s ein
EndIf
If RType.l = 68 ; Hex 44 - Opaque
; Keine Information wie das aufgebaut ist... Wie das aussieht. Angelich Octet String... werde es so mal Programmieren
readpointer.l + 1
OpaqueLen.l = HexVal(RSet(Hex(Asc(PeekS(*receiveBuffer + readpointer.l, 1))), 2, "0")) ; Lese die Laenge des Opaque´s ein
readpointer + 1
*SNMPValues\Returnvalue = PeekS(*receiveBuffer + readpointer, OpaqueLen.l)
EndIf
If RType.l = 69 ; Hex 45 - NsapAddress
; Keine Information wie das aussieht im Paket
EndIf
If RType.l = 70 ; Hex 46 - Counter64 (available only in SNMPv2)
; Keine Information wie das aussieht im Paket
EndIf
If RType.l = 71 ; Hex 47 - Uinteger32 (available only in SNMPv2)
; Keine Information wie das aussieht im Paket
EndIf
*SNMPValues\Datatype = RType.l
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
Else
ProcedureReturn #False
EndIf
Else
ProcedureReturn #False ; Liefere einen Fehler zurück
EndIf
EndProcedure
Procedure HexVal(a$); - Convert a String in hexdecimal-format in numeric value
a$=Trim(UCase(a$))
If Asc(a$)='$'
a$=Trim(Mid(a$,2,Len(a$)-1))
EndIf
Result=0
*adr.BYTE=@a$
For i=1 To Len(a$)
Result<<4
Select *adr\b
Case '0'
Case '1':Result+1
Case '2':Result+2
Case '3':Result+3
Case '4':Result+4
Case '5':Result+5
Case '6':Result+6
Case '7':Result+7
Case '8':Result+8
Case '9':Result+9
Case 'A':Result+10
Case 'B':Result+11
Case 'C':Result+12
Case 'D':Result+13
Case 'E':Result+14
Case 'F':Result+15
Default:i=Len(a$)
EndSelect
*adr+1
Next
ProcedureReturn Result
EndProcedure
Gruß,
Torakas
Nachtrag: Ich hab den Code ausgetauscht... Jetzt sollte er fast alles abfragen was wichtig ist... Wenn Fragen sind, dann am mich wenden.