Page 1 sur 1

Librairie SNMP (administration réseau)

Publié : mer. 03/janv./2007 10:59
par Golfy
j'essaie de faire une librairie SNMP mais la structure et les codes BER employés rendent ma tâche difficile (je ne suis plus un programmeur depuis plusieurs années et la reprise en Purebasic reste difficile malgré sa simplicitéd'utilisation).

Ci-dessous, le schéma d'une structure type : mon objectif étant de pouvoir récupérer les variables simples (SysUpTime, SysName, IfInByte, IfInErrorByte,... )
Image

Dois-je utiliser une liste chainé, une structure, un buffer (avec pointeurs) sachant qu'il n'est pas possibled'utiliser une chaîne de caractères (var.s ou var$) à cause des caractères $00 (null) pouvant apparaître dans la requête...

Voici également la signification de la plupart des valeurs possibles pour le codage/décodage d'une requête :

Code : Tout sélectionner

; --------------------------------------------------
;|             Librairies SNMP                      |
; --------------------------------------------------
;
; ========= CONSTANTES (pour information) ==========
; Sequence
#ASNSeq     = $30

; Primitives ASN.1 Type Identifier
#ASNInt     = $02
#ASNBitStr  = $03
#ASNOctStr  = $04
#ASNNull    = $05
#ASNOID     = $06

; Primitives SNMP application types
#SNMPIPaddr = $40
#SNMPcount  = $41
#SNMPGauge  = $42
#SNMPTimeTic= $43
#SNMPOpaque = $44
#SNMPNSAPAd = $45
#SNMPCnt64  = $46  ; SNMP v2 only
#SNMPUInt32 = $47  ; SNMP v2 only

; Context-specific type SNMP message
#SNMPGetReq = $a0
#SNMPNxtReq = $a1
#SNMPResp   = $a2
#SNMPSetReq = $a3
#SNMPTrap   = $a4  ; obsolete in SNMP v2
#SNMPBlkReq = $a5  ; Added in SNMP v2
#SNMPInfReq = $a6  ; Added in SNMP v2
#SNMPTrapV2 = $a7  ; Added in SNMP v2

Publié : mer. 03/janv./2007 12:05
par lionel_om
C'est quoi ce tableau ? Un fichier Excel ?

Publié : mer. 03/janv./2007 12:07
par Progi1984
Regarde ici :
http://www.purebasic.fr/german/viewtopi ... light=snmp

Un code qui pourrait surement t'intéresser !

Publié : mer. 03/janv./2007 15:27
par Golfy
En effet 8O ! merci Progi1984 :D

(par contre le code est "assez hermétique" à lire et je ne voudrais pas trop "plagier")

lionel_om : oui, j'ai mis les informations dans un tableau Excel pour garder une trace électronique.
Il s'agit d'une capture de trame + recherches sur le protocole SNMP (Google est mon ami) mais j'avais oublié le forum purebasic allemand...

Publié : mer. 03/janv./2007 16:59
par lionel_om
Car y'a Flype (je crois :roll: ) qui a fait une "Lib" pour ouvrir des fichiers Excels.

Publié : mer. 03/janv./2007 19:19
par Dr. Dri
Y'a aussi LeCyb qui bosse là dessus, essaye de le contacter

Dri

Publié : jeu. 04/janv./2007 14:59
par Golfy
Comment dois-je faire pour trouver LeCyb dans la liste des membres ?

Sinon, je viens de terminer la fonction CodageValeur et DecodageValeur (format ASN-1 BER).

Les voici :

Code : Tout sélectionner

Procedure.l CodeValeur(valeur.l, *b)
	; procédure TERMINE (100%)
	; CodeValeur permet de coder une valeur au format INTEGER décrit dans ASN.1
	; Valeur < 128 --> 1 byte, 16384 < valeur < 128 --> 2 bytes, etc...
	Debug "-------- Procedure CodeValeur"
	*temp = AllocateMemory(64)
	d.l = 1
	t.l = 0
	While valeur > 127
		If d = 1												; Warning : last byte doesn't have 8th bit set to '1'
			reste = valeur % 128					;           (dernier octet ne doit pas avoir 8eme bit a '1')
		Else														; other byte (MSB) should have 8th bit set to '1'
			reste = valeur % 128 + 128		;
		EndIf
		PokeB(*temp+d, reste)
		deb$ = Str(reste)+"/" + deb$
		valeur = Int(valeur/128)
		d = d + 1
	Wend
	PokeB(*temp+d, valeur+128)
	deb$ = Str(valeur+128)+"/" + deb$
	Debug deb$
	For t=0 To d-1										; Write data in the right order
		PokeB(*b+d-t-1,PeekB(*temp+t+1))
		Debug "["+Str(PeekB(*b+t))+"]";
	Next t
	For t = 0 To d-1
		Debug "Oct("+Str(t)+") = "+Str(PeekB(*b+t))
	Next t
	ProcedureReturn d									; return length's data (renvoit la longeur de la donnée)
EndProcedure
Procedure.l DecodeValeur(long.l, *b)
	; Procédure TERMINE (100%)
	; 128^t -> t:0 = 1, t:1 = 128, t:2 = 16384...
	Debug "------ Procedure DecodeValeur"
	valeur.l = 0
	octet.l = 0
	For t = 0 To long-1
		If t < long-1
			octet.l = (PeekB(*b+t)+128)%128
		Else
			octet.l = PeekB(*b+t) 
		EndIf
		Debug "Oct("+Str(t)+") = "+Str(octet.l)
		Debug "128^"+Str(long-t-1)
		valeur.l = valeur.l + (octet.l * Pow(128,long-t-1))

		Debug "Valeur = "+Str((octet.l * Pow(128,long-t-1)))
	Next t
	ProcedureReturn valeur.l
EndProcedure

Publié : jeu. 04/janv./2007 23:05
par Dr. Dri
Profil de LeCyb

Dri ;)

Publié : jeu. 04/janv./2007 23:08
par Golfy
C'était un peu trop compliqué alors j'ai pris le problème à l'envers : beaucoup plus facile ainsi de créer une requête SNMP dans le bon format ! 8)
Ensuite une procédure inverse le buffer mémoire pour présenter la requête dans le bon sens sur l'interface réseau...
Je teste ça demain (avec Wireshark) et l'analyse d'une trame entrante devrait être moins difficile !

J'ai abandonné l'utilisation du code allemand car certaines subtilités du langage ASN-1 n'étaient pas respectées ==> moins compatible avec les différentes requêtes possibles :(

Code : Tout sélectionner

OID.s = "1.3.6.1.2.1.4096"
*OIDBuffer = AllocateMemory(1024)
long = CodeValeur(1045, *OIDBuffer)
Debug "Longeur = "+Str(long)
;a = DecodeValeur(long, *OIDBuffer)
;Debug "Resultat = "+Str(a)

Debug "--------------------------------------"
longueur = OIDCode(OID.s, "SELEC", *OIDBuffer)
a = inverseBuffer(*OIDBuffer, longueur)


Procedure.l OIDCode(OID.s, Community.s, *OIDbuffer)
	; la procédure écrit la requête à l'envers (1er oct. = Fin de l'OID)
	; 100% TERMINE
	OIDinverse.s = inverse(OID.s)
	nbParam = CountString(OIDinverse.s, ".")
	lng = 2																				; Offset +2 ($00 $05)
	PokeB(*OIDBuffer,$00)													; End of OID
	PokeB(*OIDBuffer+1,$05)												; NULL Type ($05)

	For t = 1 To nbParam-1												; Loop but avoid 2 last values (3.1)
		valeur = Val(StringField(OIDinverse.s, t, "."));  
		longueur = CodeValeur(valeur, *OIDBuffer+lng)
		Debug Str(valeur)+". ==> "+Str(PeekB(*OIDBuffer+lng)+128)
		lng = lng + longueur
	Next t
	PokeB(*OIDBuffer+lng, $2B)										; 1.3. is coded $2B ==> don't check 2 first values
	lng = lng + 1																	; $2B = 1 byte
	Llng = CodeValeur(lng, *OIDBuffer+lng)				; get the LEN of lng encoding (one or more byte)
	Debug "longueur OID = "+Str(lng)+" codé sur "+Str(Llng)+" oct."
	; il faut ajout $30 L1 $30 L2 $06 lng [$2B + OID]
	lng = lng + Llng
	PokeB(*OIDBuffer+lng, $06)
	Llng = CodeValeur(lng, *OIDBuffer+lng)				; Llng = lng + 1 (could be coded on more than 1 byte)
	lng = lng + Llng															; add Llng to lng (how many byte were added...)
	PokeB(*OIDBuffer+lng, $30)
	Llng = CodeValeur(lng, *OIDBuffer+lng)				; Llng = lng + 1 (could be coded on more than 1 byte)
	lng = lng + Llng															; add Llng to lng (how many byte were added...)
	PokeB(*OIDBuffer+lng, $30)
	;
	PokeB(*OIDBuffer+lng+1,$00)										;  T L(V) ERROR INDEX
	PokeB(*OIDBuffer+lng+2,$01)										;  T(L)V  1 byte length
	PokeB(*OIDBuffer+lng+3,$02)										; (T)L V  Integer (type 2)
	PokeB(*OIDBuffer+lng+4,$00)										;  T L(V) ERROR STATUS
	PokeB(*OIDBuffer+lng+5,$01)										;  T(L)V
	PokeB(*OIDBuffer+lng+6,$02)										; (T)L V
	PokeB(*OIDBuffer+lng+7,$01)										;  T L(V) ID SEQUENCE
	PokeB(*OIDBuffer+lng+8,$01)										;  T(L)V
	PokeB(*OIDBuffer+lng+9,$02)										; (T)L V
	lng = lng + 10
	Llng = CodeValeur(lng, *OIDBuffer+lng)				; Llng = lng + 1 (could be coded on more than 1 byte)
	lng = lng + Llng															; add Llng to lng (how many byte were added...)
	PokeB(*OIDBuffer+lng, $A0)										; GET REQUEST	
	lng = lng + 1
	;
	L = Len(community.s)													; COMMUNITY
	PokeS(*OIDBuffer+lng, inverse(Community.s), L, #PB_Ascii)
	lng = lng + L
	Llng = CodeValeur(L, *OIDBuffer+lng)					;  T(L)V  Community Length
	lng = lng + Llng															; add Llng to lng (how many byte were added...)
	PokeB(*OIDBuffer+lng, $04)										; (T)L V  Community Type	
	PokeB(*OIDBuffer+lng+1,$00)										;  T L(V) VERSION
	PokeB(*OIDBuffer+lng+2,$01)										;  T(L)V  1 byte length
	PokeB(*OIDBuffer+lng+3,$02)										; (T)L V  Integer (type 2)
	lng = lng + 4
	Llng = CodeValeur(lng, *OIDBuffer+lng)				; Llng = lng + 1 (could be coded on more than 1 byte)
	lng = lng + Llng															; add Llng to lng (how many byte were added...)
	PokeB(*OIDBuffer+lng, $30)										; GET REQUEST	

	a$ = ""
	For t=0 To lng
		a$=a$+" $"+Hex(PeekC(*OIDBuffer+t))
	Next t
	Debug a$
	ProcedureReturn lng
EndProcedure		

Procedure.l CodeValeur(valeur.l, *b)
	; Procedure OK (100%)
	; CodeValeur permet de coder une valeur au format INTEGER décrit dans ASN.1
	; Valeur < 128 --> 1 byte, 16384 < valeur < 128 --> 2 bytes, etc...
	Debug "-------- Procedure CodeValeur"
	d.l = 0
	While valeur > 127
		reste = valeur % 128 + 128		;
		PokeB(*b+d, reste)
		deb$ = Str(reste)+"/" + deb$
		valeur = Int(valeur/128)
		d = d + 1
	Wend
	PokeB(*b+d, valeur)
	deb$ = Str(valeur+128)+"/" + deb$
	; Debug deb$
	;	For t = 0 To d
	;		Debug "Oct("+Str(t)+") = "+Str((PeekB(*b+t)+128)%128)
	;	Next t
	ProcedureReturn d+1									; return length's data (renvoit la longeur de la donnée)
EndProcedure
Procedure.l DecodeValeur(long.l, *b)
	; Procédure TERMINE (100%)
	; 128^t -> t:0 = 1, t:1 = 128, t:2 = 16384...
	Debug "------ Procedure DecodeValeur"
	valeur.l = 0
	octet.l = 0
	For t = 0 To long-1
		If t < long-1
			octet.l = (PeekB(*b+t)+128)%128
		Else
			octet.l = PeekB(*b+t) 
		EndIf
		valeur.l = valeur.l + (octet.l * Pow(128,long-t-1))
		; Debug "Valeur = "+Str((octet.l * Pow(128,long-t-1)))
	Next t
	ProcedureReturn valeur.l
EndProcedure

Procedure.s inverse(chaine.s)
	; Procedure OK (100%)
	a.s = ""
	lng.l = CountString(chaine.s,".")+1
	For t=1 To lng.l
		a.s = a.s + "."+StringField(chaine.s,lng.l - t+1,".")
	Next t
	a.s = Right(a.s, Len(a.s)-1)
	Debug chaine.s
	Debug a.s
	ProcedureReturn a.s
EndProcedure
Procedure.l inverseBuffer(*buffer, longueur.l)
	*buffer2 = AllocateMemory(longueur.l)
	; a$=""
	For t = 0 To longueur
		PokeB(*buffer2+t, PeekB(*buffer+longueur-t))
		; a$=a$+" $"+Hex(PeekC(*Buffer2+t))
	Next t
	; Debug a$
	CopyMemory(*buffer2, *buffer, longueur)
	FreeMemory(*buffer2)
	ProcedureReturn 0
EndProcedure


Bonne nuit !

PS : si quelqu'un peut me dire comment afficher correctement mon code sur le forum... :oops:

Publié : ven. 05/janv./2007 7:37
par Dr. Dri
Je viens de me rendre compte que LeCyb n'a jamais bossé là dessus
(à ma connaissance)

En fait j'ai confondu avec un collègue

Dri :oops: