Librairie SNMP (administration réseau)

Programmation d'applications complexes
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Librairie SNMP (administration réseau)

Message 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
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

C'est quoi ce tableau ? Un fichier Excel ?
Avatar de l’utilisateur
Progi1984
Messages : 2659
Inscription : mar. 14/déc./2004 13:56
Localisation : France > Rennes
Contact :

Message par Progi1984 »

Regarde ici :
http://www.purebasic.fr/german/viewtopi ... light=snmp

Un code qui pourrait surement t'intéresser !
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Message 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...
lionel_om
Messages : 1500
Inscription : jeu. 25/mars/2004 11:23
Localisation : Sophia Antipolis (Nice)
Contact :

Message par lionel_om »

Car y'a Flype (je crois :roll: ) qui a fait une "Lib" pour ouvrir des fichiers Excels.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Y'a aussi LeCyb qui bosse là dessus, essaye de le contacter

Dri
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Message 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
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Profil de LeCyb

Dri ;)
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Message 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:
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message 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:
Répondre