Envoi de traps snmp

Description

Ce petit bout de code permet d'envoyer un trap SNMP vers un manager SNMP de votre choix. Ce mode de communication est celui utilisé par les équipements réseaux pour informer les aministrateurs des dysfonctionnements rencontrés et est de plus en plus répandu chez les éditeurs de logiciels car il a l'avantage d'être normalisé et donc géré par la quasi totalité des logiciels de supervision. La fonction GetIPAdress utilisée par mon code n'est pas de moi (il faut rendre à César...) mais un bout de code trouvé justement sur CodeS-SourceS.

Pour l'utiliser, mettre ce bout de code dans un module et faire appel à la fonction "SnmpTrap" en lui indiquant un composant Winsock que vous aurez préalablement créé.
Petite précision : Le paramètre "Variables" doit être un tableau de chaines de caractères (je l'ai déclaré en Variant sinon je ne pouvais pas utiliser l'instruction "IsMissing").

Pour simplifier le programme et rendre cette fonction facilement utilisable, je n'ai qu'un seul type de variables : des chaines de caractères (je n'utilise pas les types entiers, timestamp,... du protocole) sinon, ça rend la mise sous forme de fonction trop lourde et n'avait que peu d'intérêt dans la plupart des cas...

Pour ceux qui ne connaissent pas bien le protocole SNMP, les incontournables pour utiliser cette fonction sont :
- L'OID est une chaine de caractères représentant d'une part l'élément émetteur (un constructeur d'équipement, un éditeur de soft,...) et le problème (ou l'information) en question sous forme de numériques séparés par des ".". Les OIDs commencent toujours par ".1.3". Exemple : .1.3.6.1.4.1.482
- Le generic est un élément permettant de définir le type de problème. Dans notre cas (celui d'un programme tournant sur une machine), sa valeur est toujours égale à "6" (=trap d'entreprise) (mais si vous voulez simuler des messages de tombées d'interfaces réseau, vous le pouvez...). Valeur de 0 à 6
- Le specific est un sous-type du message et est uniquement intéressant que le generic vaut 6. A vous de le définir (valeur de 0 à 255)
- La communauté : j'utilise toujours la communauté "public", mais il est aussi possible de préciser "private" (jamais testé)

Pour plus de détails sur le protocole SNMP, il vous reste aussi les RFC...

Source / Exemple :


Public Type WSADATA
    wVersion As Integer
    wHighVersion As Integer
    szDescription As String * 257
    szSystemStatus As String * 129
    iMaxSockets As Long
    iMaxUdpDg As Long
    lpVendorInfo As Long
End Type
Public Declare Function WSAStartup Lib "wsock32.dll" (ByVal wVersionRequested As Integer, lpWSAData _
    As WSADATA) As Long
Public Declare Function WSACleanup Lib "wsock32.dll" () As Long
Public Type HOSTENT
    h_name As Long
    h_aliases As Long
    h_addrtype As Integer
    h_length As Integer
    h_addr_list As Long
End Type

Public Const AF_INET = 2

Public Declare Function gethostbyname Lib "wsock32.dll" (ByVal name As String) As Long
Public Declare Function inet_ntoa Lib "wsock32.dll" (ByVal inaddr As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source _
    As Any, ByVal length As Long)
Public Declare Function lstrlen Lib "kernel32.dll" Alias "lstrlenA" (ByVal lpString As Any) As Long
Public Declare Function lstrcpy Lib "kernel32.dll" Alias "lstrcpyA" (ByVal lpString1 As Any, ByVal _
    lpString2 As Any) As Long

Public Type Var_snmp
    Marq_seq As Byte
    Len_tot As Byte
    Len_tot1 As Byte
    Len_tot2 As Byte
    Type_oid As Byte
    Len_oid As Byte
    OID() As Byte
    Type_var As Byte
    Len_var As Byte
    Len_var1 As Byte
    Len_var2 As Byte
    Var() As Byte
End Type

Public Type PaqSnmp
    Entete As Byte
    Longueur_Totale As Byte
    Longueur_Totale1 As Byte
    Longueur_Totale2 As Byte
    Version_type As Byte 'toujours =2 (ENTIER)
    Version_longueur As Byte 'toujours =1
    Version As Byte 'toujours =0 (SNMP v1)
    Comm_type As Byte
    Comm_longueur As Byte
    Community() As Byte
    Type_snmp As Byte 'toujours=&HA4 (=envoi de trap)
    Longueur_trap As Byte
    Longueur_trap1 As Byte
    Longueur_trap2 As Byte
    ID_obj As Byte 'toujours=6 (=OID)
    Longueur_OID As Byte
    OID() As Byte
    Addr_type As Byte
    Addr_len As Byte
    Addr(0 To 3) As Byte
    Gen_type As Byte
    Gen_len As Byte
    Gen As Byte
    Spe_type As Byte
    Spe_len As Byte
    Spe As Byte
    Time_type As Byte
    Time_len As Byte
    TimeStick(0 To 3) As Byte
    Marq_seq As Byte 'toujours=&H30
    Len_var As Byte
    Len_var1 As Byte
    Len_var2 As Byte
    Liste_var() As Var_snmp
End Type

Public Function MAKEWORD(ByVal bLow As Byte, ByVal bHigh As Byte) As Integer
    MAKEWORD = Val("&H" & Right("00" & Hex(bHigh), 2) & Right("00" & Hex(bLow), 2))
End Function

Public Function GetIPAdress(ByVal HostName As String) As String

    Dim sockinfo As WSADATA
    Dim hostinfo As HOSTENT
    Dim pHostinfo As Long
    Dim pIPAddress As Long
    Dim ipAddress As Long
    Dim pIPString As Long
    Dim ipString As String
    Dim retval As Long
    
    ' Open up a Winsock session, using version 2.2.
    retval = WSAStartup(MAKEWORD(2, 2), sockinfo)
    If retval <> 0 Then
        Debug.Print "ERROR: Attempt to open Winsock failed: error"; retval
        GetIPAdress = "0.0.0.0"
        Exit Function
    End If
    
    ' Get information about the domain specified in txtDomain.
    pHostinfo = gethostbyname(HostName)
    If pHostinfo = 0 Then
        GetIPAdress = "0.0.0.0"
    Else
        ' Copy the data into a HOSTENT structure.
        CopyMemory hostinfo, ByVal pHostinfo, Len(hostinfo)
        If hostinfo.h_addrtype <> AF_INET Then
            GetIPAdress = "0.0.0.0"
        Else
            ' Copy the pointer to the first (and probably only) IP address in the structure.
            CopyMemory pIPAddress, ByVal hostinfo.h_addr_list, 4
            ' Copy the actual IP address.
            CopyMemory ipAddress, ByVal pIPAddress, 4
            ' Convert the IP address into a human-readable string.
            pIPString = inet_ntoa(ipAddress)
            ' Copy the result into a string variable.
            ipString = Space(lstrlen(pIPString))
            retval = lstrcpy(ipString, pIPString)
            ' Print the result: a human-readable IP address.
            GetIPAdress = ipString
        End If
    End If
    
    ' Close the Winsock session.
    retval = WSACleanup()
End Function

Public Sub SnmpTrap(ByVal Community As String, ByVal OID As String, ByVal Generic As Integer, ByVal Specific As Integer, ByVal Destinataire As String, ByVal Source As String, Socket As Winsock, Optional ByVal Variables As Variant)
    Dim Result() As Byte
    Dim TmpStruct As PaqSnmp
    Dim TbOID As Variant
    Dim TbAdrSrc As Variant
    Dim Isvariables As Boolean
    Dim Taille_var As Long
    Dim TmpTaille As Integer
    Dim pos As Long
    Dim i, j As Integer
    Dim decrvar As Integer
    
    Source = Trim(Source)
    Destinataire = Trim(Destinataire)
    Community = Trim(Community)
    If IsMissing(Variables) Then
        Isvariables = False
    Else
        Isvariables = True
    End If
    OID = Trim(OID)
    If Specific > 255 Then Specific = 1
    If Generic > 255 Then Generic = 1
    If Community = "" Then Exit Sub
    If (OID = "") Or Not (OID Like ".1.3.*") Then Exit Sub
    If Destinataire = "" Or Source = "" Then Exit Sub
    Source = GetIPAdress(Source)
    TbAdrSrc = Split(Source, ".")
    If UBound(TbAdrSrc) <> 3 Then Exit Sub
    OID = Right(OID, Len(OID) - 5)
    TbOID = Split(OID, ".")
    With TmpStruct
        .Entete = &H30
        .Addr_type = &H40
        .Addr_len = 4
        For i = 0 To 3
            .Addr(i) = TbAdrSrc(i)
        Next i
        .Comm_longueur = Len(Community)
        .Comm_type = 4
        ReDim .Community(0 To .Comm_longueur - 1)
        For i = 0 To .Comm_longueur - 1
            .Community(i) = Asc(Mid(Community, i + 1, 1))
        Next i
        .Gen = Generic
        .Gen_len = 1
        .Gen_type = 2
        .ID_obj = 6
        .Marq_seq = &H30
        .Spe = Specific
        .Spe_len = 1
        .Spe_type = 2
        .Time_len = 4
        .Time_type = &H43
        .TimeStick(0) = 0
        .TimeStick(1) = 0
        .TimeStick(2) = 0
        .TimeStick(3) = 0
        .Type_snmp = &HA4
        .Version = 0
        .Version_longueur = 1
        .Version_type = 2
        .Longueur_OID = UBound(TbOID) + 2
        ReDim .OID(0 To .Longueur_OID - 1)
        .OID(0) = &H2B
        pos = 0
        i = 1
        While i <= UBound(.OID)
            If Val(TbOID(pos)) > 127 Then
                .Longueur_OID = .Longueur_OID + 1
                ReDim Preserve .OID(0 To .Longueur_OID - 1)
                .OID(i) = (TbOID(pos) \ 128) + 128
                i = i + 1
                .OID(i) = TbOID(pos) Mod 128
            Else
                .OID(i) = TbOID(pos)
            End If
            pos = pos + 1
            i = i + 1
        Wend
        Taille_var = 0
        decrvar = 0
        If Isvariables Then
            ReDim .Liste_var(0 To UBound(Variables) - LBound(Variables))
            For i = 0 To UBound(.Liste_var)
                .Liste_var(i).Marq_seq = &H30
                
                Variables(i + LBound(Variables)) = Trim(Variables(i + LBound(Variables)))
                If Len(Variables(i + LBound(Variables))) > 255 Then
                   .Liste_var(i).Len_var1 = Len(Variables(i + LBound(Variables))) \ 255
                   .Liste_var(i).Len_var2 = Len(Variables(i + LBound(Variables))) Mod 255
                   .Liste_var(i).Len_var = 130
                Else
                    If Len(Variables(i + LBound(Variables))) > 127 Then
                        .Liste_var(i).Len_var1 = Len(Variables(i + LBound(Variables)))
                        .Liste_var(i).Len_var = 129
                    Else
                        .Liste_var(i).Len_var = Len(Variables(i + LBound(Variables)))
                    End If
                End If
                .Liste_var(i).Type_oid = 6
                .Liste_var(i).Len_oid = .Longueur_OID + 1
                ReDim .Liste_var(i).OID(0 To .Liste_var(i).Len_oid - 1)
                .Liste_var(i).OID(0) = &H2B
                For j = 1 To UBound(.OID)
                    .Liste_var(i).OID(j) = .OID(j)
                Next j
                .Liste_var(i).OID(UBound(.Liste_var(i).OID)) = i + 1
                .Liste_var(i).Type_var = 4
                If .Liste_var(i).Len_var > 0 Then
                    ReDim .Liste_var(i).Var(0 To Len(Variables(i + LBound(Variables))) - 1)
                    For j = 0 To UBound(.Liste_var(i).Var)
                        .Liste_var(i).Var(j) = Asc(Mid(Variables(i + LBound(Variables)), j + 1, 1))
                    Next j
                End If
                TmpTaille = Len(Variables(i + LBound(Variables))) + Val(.Liste_var(i).Len_oid) + 4
                If TmpTaille > 255 Then
                    .Liste_var(i).Len_tot = 130
                    .Liste_var(i).Len_tot1 = TmpTaille \ 256
                    .Liste_var(i).Len_tot2 = TmpTaille Mod 256
                Else
                    If TmpTaille > 127 Then
                        .Liste_var(i).Len_tot = 129
                        .Liste_var(i).Len_tot1 = TmpTaille
                        decrvar = decrvar - 1
                    Else
                        .Liste_var(i).Len_tot1 = 0
                        .Liste_var(i).Len_tot2 = TmpTaille
                        decrvar = decrvar - 2
                    End If
                End If
                Taille_var = Taille_var + TmpTaille + 4
            Next i
        End If
        Taille_var = Taille_var + decrvar

        If Taille_var > 255 Then
            .Len_var = 130
            .Len_var1 = Taille_var \ 256
            .Len_var2 = Taille_var Mod 256
            Taille_var = Taille_var + 24 + .Longueur_OID
        Else
            If Taille_var > 127 Then
                .Len_var = 129
                .Len_var1 = Taille_var
                Taille_var = Taille_var + 23 + .Longueur_OID
            Else
                .Len_var1 = 0
                .Len_var2 = Taille_var
                Taille_var = Taille_var + 22 + .Longueur_OID
            End If
        End If
        If Taille_var > 255 Then
            .Longueur_trap = 130
            .Longueur_trap1 = Taille_var \ 256
            .Longueur_trap2 = Taille_var Mod 256
            Taille_var = Taille_var + 9 + .Comm_longueur
        Else
            If Taille_var > 127 Then
                .Longueur_trap = 129
                .Longueur_trap1 = Taille_var
                Taille_var = Taille_var + 8 + .Comm_longueur
            Else
                .Longueur_trap1 = 0
                .Longueur_trap2 = Taille_var
                Taille_var = Taille_var + 7 + .Comm_longueur
            End If
        End If
        'Taille_var = Taille_var + 2
        
        If Taille_var > 255 Then
            .Longueur_Totale = 130
            .Longueur_Totale1 = Taille_var \ 256
            .Longueur_Totale2 = Taille_var Mod 256
            ReDim Result(0 To Taille_var + 3)
        Else
            If Taille_var > 127 Then
                .Longueur_Totale = 129
                .Longueur_Totale1 = Taille_var
                ReDim Result(0 To Taille_var + 2)
            Else
                .Longueur_Totale1 = 0
                .Longueur_Totale2 = Taille_var
                ReDim Result(0 To Taille_var + 1)
            End If
        End If
        
        Result(0) = .Entete
        If .Longueur_Totale = 130 Then
            Result(1) = .Longueur_Totale
            Result(2) = .Longueur_Totale1
            Result(3) = .Longueur_Totale2
            pos = 4
        Else
            If .Longueur_Totale = 129 Then
                Result(1) = .Longueur_Totale
                Result(2) = .Longueur_Totale1
                pos = 3
            Else
                pos = 2
                Result(1) = .Longueur_Totale2
            End If
        End If
        Result(pos) = .Version_type
        Result(pos + 1) = .Version_longueur
        Result(pos + 2) = .Version
        Result(pos + 3) = .Comm_type
        Result(pos + 4) = .Comm_longueur
        pos = pos + 5
        For i = 0 To UBound(.Community)
            Result(pos) = .Community(i)
            pos = pos + 1
        Next i
        Result(pos) = .Type_snmp
        If .Longueur_trap = 130 Then
            Result(pos + 1) = .Longueur_trap
            Result(pos + 2) = .Longueur_trap1
            Result(pos + 3) = .Longueur_trap2
            pos = pos + 4
        Else
            If .Longueur_trap = 129 Then
                Result(pos + 1) = .Longueur_trap
                Result(pos + 2) = .Longueur_trap1
                pos = pos + 3
            Else
                Result(pos + 1) = .Longueur_trap2
                pos = pos + 2
            End If
        End If
        Result(pos) = .ID_obj
        Result(pos + 1) = .Longueur_OID
        pos = pos + 2
        For i = 0 To UBound(.OID)
            Result(pos) = .OID(i)
            pos = pos + 1
        Next i
        Result(pos) = .Addr_type
        Result(pos + 1) = .Addr_len
        pos = pos + 2
        For i = 0 To 3
            Result(pos) = .Addr(i)
            pos = pos + 1
        Next i
        Result(pos) = .Gen_type
        Result(pos + 1) = .Gen_len
        Result(pos + 2) = .Gen
        Result(pos + 3) = .Spe_type
        Result(pos + 4) = .Spe_len
        Result(pos + 5) = .Spe
        Result(pos + 6) = .Time_type
        Result(pos + 7) = .Time_len
        pos = pos + 8
        For i = 0 To 3
            Result(pos) = .TimeStick(i)
            pos = pos + 1
        Next i
        Result(pos) = .Marq_seq
        If .Len_var = 130 Then
            Result(pos + 1) = .Len_var
            Result(pos + 2) = .Len_var1
            Result(pos + 3) = .Len_var2
            pos = pos + 4
        Else
            If .Len_var = 129 Then
                Result(pos + 1) = .Len_var
                Result(pos + 2) = .Len_var1
                pos = pos + 3
            Else
                Result(pos + 1) = .Len_var2
                pos = pos + 2
            End If
        End If
        If Isvariables Then
            For i = 0 To UBound(.Liste_var)
                Result(pos) = .Liste_var(i).Marq_seq
                If .Liste_var(i).Len_tot = 130 Then
                    Result(pos + 1) = .Liste_var(i).Len_tot
                    Result(pos + 2) = .Liste_var(i).Len_tot1
                    Result(pos + 3) = .Liste_var(i).Len_tot2
                    pos = pos + 4
                Else
                    If .Liste_var(i).Len_tot = 129 Then
                        Result(pos + 1) = .Liste_var(i).Len_tot
                        Result(pos + 2) = .Liste_var(i).Len_tot1
                        pos = pos + 3
                    Else
                        Result(pos + 1) = .Liste_var(i).Len_tot2
                        pos = pos + 2
                    End If
                End If
                Result(pos) = .Liste_var(i).Type_oid
                Result(pos + 1) = .Liste_var(i).Len_oid
                pos = pos + 2
                For j = 0 To UBound(.Liste_var(i).OID)
                    Result(pos) = .Liste_var(i).OID(j)
                    pos = pos + 1
                Next j
                Result(pos) = .Liste_var(i).Type_var
                If .Liste_var(i).Len_var = 130 Then
                    Result(pos + 1) = .Liste_var(i).Len_var
                    Result(pos + 2) = .Liste_var(i).Len_var1
                    Result(pos + 3) = .Liste_var(i).Len_var2
                    pos = pos + 4
                    ReDim Preserve Result(0 To UBound(Result) + 2)
                Else
                    If .Liste_var(i).Len_var = 129 Then
                        Result(pos + 1) = .Liste_var(i).Len_var
                        Result(pos + 2) = .Liste_var(i).Len_var1
                        pos = pos + 3
                        ReDim Preserve Result(0 To UBound(Result) + 1)
                    Else
                        Result(pos + 1) = .Liste_var(i).Len_var
                        pos = pos + 2
                    End If
                End If
                
                If .Liste_var(i).Len_var > 0 Then
                    For j = 0 To UBound(.Liste_var(i).Var)
                        Result(pos) = .Liste_var(i).Var(j)
                        pos = pos + 1
                    Next j
                End If
            Next i
        End If
    End With
    Socket.RemoteHost = Destinataire
    Socket.RemotePort = 162
    If Socket.Protocol <> sckUDPProtocol Then Socket.Protocol = sckUDPProtocol
    Socket.SendData Result
End Sub

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.