# SNMP

> Les équipements réseau qui répondent en SNMP v1, v2c ou v3 (onduleurs, PDU, commutateurs, routeurs, climatisation de précision et capteurs d'ambiance) lus par leur agent à l'intervalle de scrutation de chaque tag : la carte Agent SNMP, l'OID d'un tag en chiffres ou par son nom standard, les types de donnée dans lesquels chaque objet se lit, la lecture et l'écriture, le parcours qui découvre les objets d'un agent, et deux exemples complets.

Le pilote **SNMP** lit et écrit les équipements d'une salle technique par leur agent SNMP : onduleurs,
PDU, commutateurs, routeurs, climatisation de précision et capteurs de température ou d'humidité. Il
complète le pilote [Redfish](driver-redfish), qui lit les contrôleurs de gestion des serveurs : à eux
deux, ils couvrent la salle technique. Chaque tag lit un objet de l'agent par son OID, comme
`upsBatteryStatus.0` ou `ifHCInOctets.2`, et ses valeurs arrivent là où arrivent celles de tout autre
tag : dans Logic, sur les tableaux de bord, dans les essais d'un banc de test de [Process](process).

C'est la station qui interroge : chaque tag est lu à son intervalle de scrutation, en SNMPv1, SNMPv2c
ou SNMPv3, et l'**Intervalle de scrutation (ms)** de la carte Équipement fonctionne comme sous tout
pilote, chaque tag pouvant le remplacer. Ce que l'équipement envoie de lui-même, ses traps, n'est pas
reçu ; voir [Limites à connaître](#limits-worth-knowing).

Un équipement de ce pilote est un agent, joint sur son hôte par le port UDP 161. Les équipements se
rangent sous le pilote et peuvent être classés dans des dossiers,
**Pilote → Dossier → Équipement → Tag**, comme sous tout pilote sans ligne série ni broker.

## La page du pilote {#the-drivers-page}

Pour Configurer le connector, la page porte la carte Portée du balayage propre au pilote, avec l'agent
et les sous-arbres que Découvrir parcourt (voir [Découverte](#discovery)). En dessous se trouve le
tableau **Équipements** de tout pilote (voir
[Le tableau des équipements](connector-drivers#the-device-table)), qui grandit avec
**Ajouter un équipement**, à droite de son titre ; vide, il indique « Aucun équipement pour l'instant. »
La barre du pilote porte **Découvrir**, grisé tant que la carte Portée du balayage n'est pas complète.

## Équipement {#device}

### Connexion {#connection}

| Champ | Rôle | Par défaut |
| --- | --- | --- |
| **Hôte** | Le nom d'hôte ou l'adresse IP de l'agent. | vide |
| **Port** | Le port UDP sur lequel l'agent répond, de 1 à 65535. Une case vide affiche 161 en gris, et l'agent est interrogé sur ce port. | 161 |

Un équipement neuf n'a pas d'hôte : il indique « Hôte pas encore saisi », et rien n'est envoyé tant
qu'il n'en a pas. La Base URI qu'affiche l'en-tête est l'adresse de runtime, avec la version, la
sécurité SNMPv3 en vigueur, le délai de réponse et les nouvelles tentatives :
`snmp://192.168.10.40:161?version=2c&timeoutMs=2000&retries=1`, ou
`snmp://192.168.10.2:161?version=3&security=authPriv&auth=sha256&priv=aes128&timeoutMs=2000&retries=1`.
Elle ne porte jamais la community, l'utilisateur ni un mot de passe.

### La carte Agent SNMP {#the-snmp-agent-card}

Sous la carte Connexion, la carte **Agent SNMP** dit comment l'agent est interrogé. Les champs qu'elle
dessine suivent la version et, en SNMPv3, le niveau de sécurité.

| Champ | Affiché | Rôle | Par défaut |
| --- | --- | --- | --- |
| **Version SNMP** | toujours | SNMPv1, SNMPv2c ou SNMPv3, chacune avec une ligne en dessous. SNMPv1 : « SNMPv1 n'a pas de compteurs 64 bits, et un objet absent de l'agent fait refuser toute la requête, que le pilote reformule alors sans lui. » SNMPv2c : « SNMPv2c lit les compteurs 64 bits, et un objet absent de l'agent ne fait échouer que ce tag. La plupart des équipements le parlent. » SNMPv3 : « SNMPv3 s'identifie avec un utilisateur, et signe et chiffre ses messages selon le niveau de sécurité. » | SNMPv2c |
| **Community** | SNMPv1, SNMPv2c | La community à laquelle l'agent répond, de 255 octets au plus, dans une case qui masque la saisie ; vide, elle affiche `public` comme indication, jamais comme valeur. En dessous : « Un agent ignore une requête dont il n'accepte pas la community : une community erronée ressemble donc à un agent qui ne répond pas. » | vide |
| **Utilisateur SNMPv3** | SNMPv3 | L'utilisateur que l'agent connaît, de 32 caractères au plus. | vide |
| **Niveau de sécurité** | SNMPv3 | **Signé et chiffré (authPriv)** : « Chaque message est signé avec le mot de passe d'authentification et chiffré avec le mot de passe de confidentialité. » **Signé seulement (authNoPriv)** : « Chaque message est signé avec le mot de passe d'authentification et circule en clair. » **Ni signé ni chiffré (noAuthNoPriv)** : « Seul le nom d'utilisateur est envoyé : rien n'est signé et rien n'est chiffré. » | **Signé et chiffré (authPriv)** |
| **Protocole d'authentification** | SNMPv3, signé | MD5, SHA-1, SHA-256, SHA-384 ou SHA-512. | SHA-1 |
| **Mot de passe d'authentification** | SNMPv3, signé | Le mot de passe qui signe les messages. | vide |
| **Protocole de confidentialité** | SNMPv3, authPriv | DES, AES-128, AES-192 ou AES-256. | AES-128 |
| **Mot de passe de confidentialité** | SNMPv3, authPriv | Le mot de passe qui chiffre les messages. | vide |
| **Délai de réponse (ms)** | toujours | De 100 à 60000 : « Combien de temps une requête attend la réponse de l'agent avant d'être renvoyée. » | 2000 |
| **Nouvelles tentatives** | toujours | De 0 à 5 : « Combien de fois une requête restée sans réponse est renvoyée avant que l'équipement compte comme hors ligne. » | 1 |

Sous les deux mots de passe : « Chaque mot de passe est celui que l'agent garde pour cet utilisateur, d'au moins 8 caractères. »
L'utilisateur, le niveau de sécurité et les deux protocoles sont ceux que l'agent a configurés pour cet
utilisateur, sur la page de réglages de l'équipement lui-même : la station ne peut pas les demander à
l'agent. MD5, SHA-1 et DES sont proposés parce que beaucoup d'équipements installés n'acceptent rien de
plus récent.

Un identifiant pas encore saisi n'est pas une erreur : l'équipement est enregistré, le pilote n'envoie
rien à l'agent tant qu'il manque, et une ligne posée sous la carte dit ce qui manque, la première de
celles-ci :

| Manque | La carte dit |
| --- | --- |
| La community (SNMPv1, SNMPv2c) | « Saisissez la community à laquelle l'agent répond. D'ici là, l'équipement n'envoie rien. » |
| L'utilisateur (SNMPv3) | « Saisissez l'utilisateur SNMPv3. D'ici là, l'équipement n'envoie rien. » |
| Le mot de passe d'authentification (authNoPriv, authPriv) | « Saisissez le mot de passe d'authentification. D'ici là, l'équipement n'envoie rien. » |
| Le mot de passe de confidentialité (authPriv) | « Saisissez le mot de passe de confidentialité. D'ici là, l'équipement n'envoie rien. » |

Un équipement qui a son hôte mais à qui il manque encore un identifiant ne se connecte pas, et sa
dernière erreur nomme l'identifiant que son agent attend. Une valeur que la carte ne peut pas prendre
n'est pas enregistrée, et la carte dit pourquoi, en rouge :

| Vous saisissez | La carte dit |
| --- | --- |
| Un mot de passe d'authentification de moins de 8 caractères | « Le mot de passe d'authentification doit compter au moins 8 caractères. » |
| Un mot de passe de confidentialité de moins de 8 caractères | « Le mot de passe de confidentialité doit compter au moins 8 caractères. » |
| Un utilisateur de plus de 32 caractères, ou une community de plus de 255 octets | « L'utilisateur compte au plus 32 caractères et la community au plus 255 octets. » |
| Un délai de réponse hors de 100 à 60000, ou des nouvelles tentatives hors de 0 à 5 | La case revient à la valeur en vigueur et dit « Saisissez un nombre compris entre 100 et 60000. » ou « Saisissez un nombre compris entre 0 et 5. » |

L'enregistrement tient les mêmes règles que la carte, et le journal des actions le dit quand il en
refuse une :
« L'équipement 'UPS room 1' a un réglage SNMP que son pilote ne peut pas utiliser. Ouvrez-le et corrigez le champ que son panneau signale. »
La community et les deux mots de passe sont gardés comme tout identifiant d'équipement (voir
[Identifiants et certificats](connector-devices#credentials-and-certificates)) : protégés au repos pour
le compte Windows qui les a saisis, scellés dans l'export de la configuration, et jamais montrés dans
la Base URI, le journal technique ni la réponse d'un agent. Un identifiant saisi sous un autre compte
Windows revient vide, et l'équipement l'attend comme un identifiant jamais saisi.

## Adressage du tag {#tag-addressing}

### L'OID {#the-oid}

Un tag de ce pilote lit un objet de son agent. La carte Source de la valeur du tag porte la case
**OID**, avec l'indication
« Un OID en chiffres, par exemple 1.3.6.1.2.1.1.3.0, ou un nom standard avec son instance, par exemple sysUpTime.0, ifInOctets.2 ou upsBatteryStatus.0 »
en dessous. Chaque requête porte le numéro, quelle que soit la forme sous laquelle le tag est écrit :

| Écrit | Lu comme |
| --- | --- |
| `1.3.6.1.2.1.1.3.0`, `.1.3.6.1.2.1.1.3.0`, `iso.3.6.1.2.1.1.3.0` | Ce numéro, que le panneau nomme `sysUpTime.0`. |
| `sysUpTime.0`, `sysUpTime`, `SNMPv2-MIB::sysUpTime.0`, sans tenir compte de la casse | Une valeur unique, dont la seule instance `.0` peut être omise. |
| `ifInOctets.2` | Une colonne d'une table avec l'index de sa ligne, ici l'interface 2, qui s'écrit toujours. |
| `enterprises.318.1.1.1.2.2.1.0` | Une branche suivie des chiffres qui se trouvent dessous : un objet de la MIB propre à l'équipement, affiché par son numéro. |

Sous la case, en lecture seule, l'OID des deux façons :

| Affichage | Ce qu'il montre |
| --- | --- |
| **Nom dans la MIB** | Le nom standard de l'objet avec son instance (`ifInOctets.2`), et en dessous ce que la MIB dit de l'objet : sa MIB, le genre de valeur qu'il porte et s'il accepte l'écriture, comme `IF-MIB · Counter32 · lecture seule` ou `UPS-MIB · Integer32 · accepte l'écriture`. « Aucun nom standard » pour un objet que le pilote ne connaît pas par son nom. |
| **OID numérique** | L'OID en chiffres, ce que porte chaque requête. |

Un objet sans nom standard ajoute la ligne
« Un objet de la MIB propre à l'équipement : il apparaît par son numéro, car aucun fichier MIB n'est lu. »
Un tag dont le pilote ne peut pas lire l'OID n'est pas enregistré, et la page du tag dit pourquoi :

| Vous saisissez | La page du tag dit |
| --- | --- |
| Aucun OID | « OID est obligatoire pour ce pilote. » |
| Un nom que le pilote ne connaît pas | « Ce nom n'est pas l'un des objets MIB standard que le pilote connaît. Écrivez l'OID en chiffres. » |
| Une colonne sans sa ligne, comme `ifInOctets` | « Une colonne de table a besoin de l'index de sa ligne, par exemple ifInOctets.1. » |
| Une valeur unique avec une instance autre que 0, comme `sysUpTime.1` | « Une valeur unique a une seule instance, .0, qu'on peut omettre. » |
| Une branche seule, comme `enterprises` ou `ifTable` | « Une branche de l'arbre ne nomme aucune valeur. Écrivez les chiffres de l'objet qui se trouve dessous. » |
| Un premier nombre supérieur à 2, un deuxième de 40 ou plus, plus de 128 nombres, ou un nombre supérieur à 4294967295 | « Un OID commence par 0, 1 ou 2 suivi d'un nombre inférieur à 40, et compte au plus 128 nombres d'au plus 4294967295. » |
| Toute autre chose qui n'est pas un OID | « Écrivez l'OID en chiffres, par exemple 1.3.6.1.2.1.1.3.0, ou un nom standard avec son instance, par exemple sysUpTime.0. » |

L'enregistrement tient la même règle :
« Le tag 'Battery status' ne nomme aucun OID que le pilote SNMP puisse lire. Ouvrez-le et corrigez l'adresse que le panneau du tag signale. »
La ligne en lecture seule **Adresse source (bus)** montre le numéro que le pilote reçoit :
`1.3.6.1.2.1.33.1.2.1.0` pour un tag écrit `upsBatteryStatus.0`.

### Les noms que le pilote connaît {#the-names-the-driver-knows}

Le pilote porte une table des objets des MIB standard qui méritent un nom, écrite d'après les RFC, si
bien qu'un nom veut dire la même chose sur toute station. Aucun fichier MIB n'est lu.

| MIB | Ce qu'elle nomme |
| --- | --- |
| SNMPv2-MIB (RFC 3418) | Le groupe system : `sysDescr`, `sysObjectID`, `sysUpTime`, `sysContact`, `sysName`, `sysLocation`, `sysServices`. |
| IF-MIB (RFC 2863) | `ifNumber`, la table des interfaces (`ifDescr`, `ifOperStatus`, `ifInOctets`, `ifOutErrors` et le reste) et son extension avec les compteurs 64 bits (`ifName`, `ifHCInOctets`, `ifHCOutOctets`, `ifHighSpeed`, `ifAlias`). |
| UPS-MIB (RFC 1628) | L'identité, la batterie, l'entrée, la sortie, le bypass, les alarmes, le test, la commande et la configuration d'un onduleur : `upsBatteryStatus`, `upsEstimatedChargeRemaining`, `upsOutputSource`, `upsOutputPercentLoad` et le reste. |
| ENTITY-SENSOR-MIB (RFC 3433) | La table des capteurs : `entPhySensorType`, `entPhySensorScale`, `entPhySensorValue`, `entPhySensorOperStatus` et le reste. |
| ENTITY-MIB (RFC 6933) | Le nom, la description et la classe d'une entité physique, qui étiquettent un capteur : `entPhysicalName`, `entPhysicalDescr`, `entPhysicalClass`. |
| HOST-RESOURCES-MIB (RFC 2790) | Le système (`hrSystemUptime`, `hrSystemProcesses`), la table de stockage (`hrStorageUsed`) et la table des processeurs (`hrProcessorLoad`). |

`driver_capabilities` liste chaque nom avec son OID ; voir [Outils de l'agent](#agent-tools).

### Types de donnée et accès {#data-types-and-access}

La liste **Type de donnée** ne propose que ce dans quoi l'objet se lit sans perte :

| L'objet porte | Se lit le plus naturellement comme | Aussi proposés |
| --- | --- | --- |
| Integer32, énumérations et TruthValue compris | Int32 | Int64, Float, Double, String |
| Counter32, Gauge32, TimeTicks (centièmes de seconde) | UInt32 | Int64, Double, String |
| Counter64 | UInt64 | Double, String |
| DisplayString | String | |
| Des octets, une adresse IP ou un OID | String : les octets en hexadécimal (`00:1A:2B`), l'adresse pointée, l'OID pointé | |
| Un objet sans nom standard | Float | Int32, UInt32, Int64, UInt64, Double, String : la réponse de l'agent tranche à la lecture |

Un compteur n'est pas proposé en Float, qui arrondit au-delà de 16 777 216, ni un Counter64 en Int64,
qui refuserait un comptage au-delà de sa moitié. Boolean n'est jamais proposé : SNMP n'a pas de
booléen, et son TruthValue (1 vrai, 2 faux) et le 0 et le 1 propres à un équipement liraient le même
type de deux façons opposées, si bien qu'un état se lit en Int32. Quand l'OID change, un type dans
lequel le nouvel objet ne se lit pas devient celui dans lequel il se lit le plus naturellement ; et un
type dans lequel il ne se lit pas est refusé, en nommant ceux dans lesquels il se lit :
« ifHCOutOctets.2 se lit comme l'un de ces types : UInt64, Double, String. »

Un objet standard que sa MIB déclare en lecture seule (les compteurs, `sysUpTime`, les états) n'est
proposé qu'en **Lecture seule**, et le champ Accès dit
« Lecture seule : l'équipement signale cette valeur, et rien de l'extérieur ne la fixe. »
Un objet standard que sa MIB déclare inscriptible (`sysContact`, `sysName`, `sysLocation`,
`ifAdminStatus`, `ifAlias`, les objets de test, de commande et de configuration de l'UPS-MIB) et un
objet de la MIB propre à l'équipement reçoivent tous les accès : que l'agent accepte l'écriture est sa
propre réponse.

## Lecture {#reading}

À l'intervalle de scrutation de chaque tag, la station envoie un GET. Ce que l'agent répond décide de
ce que le tag montre (voir [La chaîne de conversion](connector-value-pipeline)) :

| L'agent répond | Ce que fait la lecture |
| --- | --- |
| La valeur | La valeur, dans le type du tag, avant que les étapes du tag lui-même ne la convertissent. Un texte qui contient un nombre (`23.5`, qu'écrivent certains équipements) se lit dans un tag numérique. |
| Une valeur que le type du tag ne peut pas porter, comme un nombre négatif dans un UInt32 | Une lecture en échec de ce tag, avec la raison ; l'équipement continue de lire ses autres tags. |
| noSuchObject ou noSuchInstance, ou une erreur sur ce seul objet | Une lecture en échec de ce tag, nommée avec la réponse de l'agent ; l'équipement continue de lire ses autres tags. En SNMPv1, où un objet absent fait refuser toute la requête, le pilote redemande sans lui. |
| Rien dans le délai de réponse, après toutes les nouvelles tentatives | Le silence : l'équipement passe hors ligne et se reconnecte, et la politique du tag pour [un équipement qui n'a pas répondu](connector-value-pipeline#the-device-did-not-answer) décide de ce qu'il montre. La cause nomme l'agent, l'attente et les tentatives, et rappelle qu'un agent se tait aussi devant une community ou un utilisateur SNMPv3 qu'il n'accepte pas. |
| Un rapport SNMPv3 (un utilisateur inconnu, un mot de passe ou un protocole erroné, un niveau de sécurité que l'agent n'accepte pas), ou la réponse de l'hôte qu'aucun agent n'écoute sur le port | Un échec de connexion avec cette cause, dans le journal technique et la dernière erreur de l'équipement ; l'équipement se reconnecte. |

Un équipement envoie une requête à la fois. Une lecture demande l'objet du tag et, dans la même
requête, les autres tags de l'équipement qui n'ont pas de réponse récente, jusqu'à 32 OID ; un agent qui
répond que la requête est trop grosse (tooBig) en reçoit moitié moins dès lors. Une réponse rapportée
ainsi sert la lecture d'un autre tag tant qu'elle est plus récente que la moitié de l'intervalle de
scrutation de ce tag, si bien que quarante tags coûtent une ou deux requêtes par passe. Le moteur d'un
agent SNMPv3 est appris une fois par connexion, et une requête que l'agent signale hors de sa fenêtre
de temps est renvoyée une fois avec les chiffres de l'agent lui-même.

## Écriture {#writing}

Un tag dont l'accès écrit envoie un SET par la file de l'équipement. Une écriture passe par le même
entonnoir que celle de tout autre pilote : la case d'écriture prend la valeur physique, et les étapes
de conversion sont inversées avant que la valeur brute ne soit envoyée (voir [Connector](connector)).
Le SET porte le genre de valeur avec lequel l'agent a répondu en dernier pour l'objet ; à défaut, celui
que déclare sa MIB ; à défaut encore, celui que répond un GET à l'instant ; et en dernier celui du tag
lui-même (un Int32 en Integer32, un UInt32 en Gauge32, un String en OCTET STRING). Une valeur que ce
genre ne peut pas porter est refusée avant tout envoi.

| L'agent répond | Ce que l'écriture signale |
| --- | --- |
| Aucune erreur | Fait. Toute réponse que l'équipement gardait est oubliée, si bien que la lecture suivante redemande. |
| Un statut d'erreur | « Écriture refusée par l'équipement : `<reason>`. », la raison nommant le statut comme l'écrit le RFC 3416, comme `notWritable (17)`, `wrongType (7)` ou `wrongValue (10)`, et `readOnly (4)` en SNMPv1. |
| Rien dans le délai de réponse, après toutes les nouvelles tentatives | « Écriture non confirmée : l'équipement n'a pas répondu à temps. » |

## Découverte {#discovery}

### La carte Portée du balayage {#the-scan-scope-card}

Pour Configurer le connector, la page du pilote porte sa carte **Portée du balayage**, sous la ligne
« Parcourt les sous-arbres standard d'un agent et liste ce qu'il trouve. Un agent SNMPv3 se balaie par son équipement : choisissez-le comme agent à balayer. »

| Champ | Rôle | Par défaut |
| --- | --- | --- |
| **Agent à balayer** | **Une adresse saisie ici**, ou un équipement du pilote par son nom. L'agent d'un équipement est lu avec son hôte, son port, sa version, ses réglages et ses identifiants tels qu'ils sont enregistrés, et une modification de l'équipement qui attend encore d'être enregistrée l'est d'abord. C'est la seule façon de balayer un agent SNMPv3. | **Une adresse saisie ici** |
| **Adresse de l'agent** | Un agent saisi : son nom d'hôte ou son adresse IP, et son port après deux-points quand ce n'est pas celui d'en dessous. | vide |
| **Port** | Un agent saisi : de 1 à 65535. | 161 |
| **Version SNMP** | Un agent saisi : SNMPv1 ou SNMPv2c. | SNMPv2c |
| **Community** | Un agent saisi : la community à laquelle il répond, dans une case qui masque la saisie, avec `public` comme indication. En dessous : « Utilisée pour ce balayage seulement. Un équipement ajouté depuis le résultat la garde comme community. » | vide |
| **Sous-arbres** | Une case chacun : **Système (SNMPv2-MIB)**, **Interfaces réseau (IF-MIB)**, **Onduleur (UPS-MIB)**, **Capteurs (ENTITY-SENSOR-MIB)** et **Ressources de l'hôte (HOST-RESOURCES-MIB)**. | tous sauf Ressources de l'hôte |
| **Parcourir aussi** | « Un sous-arbre de plus, en chiffres ou sous un nom standard, par exemple enterprises.318. Les objets propres à l'équipement reviennent en chiffres. » | vide |

Ce qui manque encore à la portée est dit en rouge sous la carte, et Découvrir reste grisé tant qu'elle
n'est pas complète :

| La portée | La carte dit |
| --- | --- |
| Un agent saisi sans adresse | « Saisissez l'adresse de l'agent SNMP à balayer. » |
| Un agent saisi dont l'adresse n'est pas un hôte | « « http://192.168.0.30 » n'est pas l'adresse d'un agent SNMP. Écrivez son nom d'hôte ou son adresse IP, avec le port au besoin, par exemple 192.168.0.30 ou 192.168.0.30:161. » |
| Un agent saisi sans community, ou avec une de plus de 255 octets | « Saisissez la community à laquelle l'agent répond, de 255 octets au plus. » |
| Un équipement qui n'existe plus | « L'équipement SNMP choisi pour le balayage n'existe plus. Choisissez un autre agent à balayer. » |
| Un équipement sans son hôte ou sans un identifiant dont son agent a besoin | « Il manque encore à l'équipement 'UPS room 1' son hôte ou un identifiant dont son agent a besoin. Complétez d'abord sa carte SNMP. » |
| Un sous-arbre à parcourir qui n'est pas un OID | « 'vendor' n'est pas un OID à parcourir. Écrivez-le en chiffres ou sous un nom standard, par exemple enterprises.318. » |
| Rien de coché et rien de nommé | « Cochez au moins un sous-arbre, ou nommez-en un à parcourir. » |

Quand l'équipement à balayer a une modification qui ne peut pas être enregistrée, le balayage ne
démarre pas :
« La découverte n'a pas démarré parce que la modification de l'équipement à balayer n'a pas pu être enregistrée. »

### Ce que le balayage propose {#what-the-scan-offers}

Découvrir demande d'abord à l'agent son nom (`sysName.0`), ce qui prouve aussi que l'agent répond à ces
identifiants, puis parcourt chaque sous-arbre coché et celui qui est nommé, avec GETBULK en SNMPv2c et
SNMPv3 et GETNEXT en SNMPv1, jusqu'à ce que l'agent réponde hors de lui. La ligne de progression compte
ce qu'il a lu :
« Parcours de l'agent SNMP à 192.168.10.40:161 : 120 objets trouvés. » Un balayage liste au plus 2000
objets et parcourt pendant au plus 60 secondes ; quand il est coupé là, ou que l'agent se tait en
chemin, il garde ce qu'il a trouvé et le dit :
« Le parcours de 192.168.10.40:161 s'est arrêté tôt, avec 2000 objets trouvés. Un balayage liste au plus 2000 objets, parcourt pendant au plus 60 s et s'arrête là où l'agent se tait. »

Le balayage propose un candidat par agent, nommé d'après son sysName (le nom de l'équipement ou l'hôte
quand l'agent n'en donne aucun), avec la version, le délai et les nouvelles tentatives avec lesquels il
a été lu, et les objets trouvés comme tags candidats :

| Objet trouvé | Nom du tag | Type de donnée | Accès |
| --- | --- | --- | --- |
| Une valeur unique que le pilote connaît par son nom | Son nom, sans le `.0` : `sysUpTime` | Celui dans lequel la valeur répondue se lit le plus naturellement | Lecture et écriture là où sa MIB le déclare inscriptible, Lecture seule sinon |
| Une colonne d'une table que le pilote connaît par son nom | Son nom et sa ligne : `ifInOctets.2` | Le même | Le même |
| Un objet de la MIB propre à l'équipement | Son numéro : `1.3.6.1.4.1.318.1.1.1.2.2.1.0` | Le même | Lecture seule |

Une valeur qu'aucun type de tag ne peut porter est laissée de côté. Un équipement ajouté depuis un
balayage saisi garde la community qu'a utilisée le balayage, protégée comme tout identifiant
d'équipement ; un équipement ajouté depuis le balayage d'un équipement porte les identifiants de cet
équipement. Un candidat dont un équipement du pilote lit déjà l'agent (l'équipement balayé, ou un autre
au même hôte et au même port) est marqué **Déjà configuré** : sa carte ne liste que les objets qu'aucun
tag de cet équipement ne lit encore, un OID écrit par son nom et par son numéro comptant pour le même,
et **Ajouter les tags**, avant **Ouvrir**, ajoute ceux qui sont cochés à cet équipement. Le reste du
comportement du balayage est sur [Découverte](connector-discovery).

La page d'un équipement fait la même chose sans la page de son pilote : **Découvrir les tags**, dans l'en-tête de sa carte **Tags**, parcourt l'agent de cet équipement avec ses réglages et identifiants, sur les sous-arbres standard et la branche du fabricant que ses tags lisent déjà (`enterprises.318` pour un tag en dessous), et ne propose que les objets pour lesquels il n'a pas encore de tag (voir [Découvrir les tags d'un équipement](connector-discovery#discovering-a-devices-tags)).

## Exemple : un onduleur en SNMPv2c {#example-a-ups-over-snmpv2c}

Un onduleur équipé d'une carte réseau répond en SNMPv2c à 192.168.10.40, avec une community de lecture
définie sur cette carte. Lisez sa batterie :

1. Sur la page du pilote, **Ajouter un équipement** ; nommez-le `UPS room 1`, saisissez **Hôte**
   192.168.10.40 et gardez **Port** 161.
2. Sur la carte **Agent SNMP**, gardez SNMPv2c, saisissez la community de lecture de la carte dans
   **Community**, et gardez un **Délai de réponse (ms)** de 2000 et 1 en **Nouvelles tentatives**. La
   ligne qui demandait la community disparaît.
3. **Ajouter un tag** `Battery status`, **OID** `upsBatteryStatus.0`, **Type de donnée** Int32. Sous la
   case, le nom dans la MIB indique upsBatteryStatus.0 avec `UPS-MIB · Integer32 · lecture seule`,
   l'OID numérique 1.3.6.1.2.1.33.1.2.1.0, et l'accès reste en Lecture seule. La valeur est 1 unknown,
   2 batteryNormal, 3 batteryLow ou 4 batteryDepleted.
4. **Ajouter un tag** `Battery charge`, **OID** `upsEstimatedChargeRemaining.0`, **Type de donnée**
   Int32, **Unité** %.
5. Si l'onduleur le signale, **Ajouter un tag** `Minutes remaining`, **OID**
   `upsEstimatedMinutesRemaining.0`, **Type de donnée** Int32, **Unité** min.

La Base URI se lit `snmp://192.168.10.40:161?version=2c&timeoutMs=2000&retries=1`. Un agent fait de
même avec les outils :

```
device_upsert name="UPS room 1" driver=Snmp host=192.168.10.40 snmpVersion=V2c snmpCommunity="<the UPS card's read community>"
tag_upsert device="UPS room 1" name="Battery status" address=upsBatteryStatus.0 opcUaType=Int32
tag_upsert device="UPS room 1" name="Battery charge" address=upsEstimatedChargeRemaining.0 opcUaType=Int32 unit=%
tag_upsert device="UPS room 1" name="Minutes remaining" address=upsEstimatedMinutesRemaining.0 opcUaType=Int32 unit=min
```

## Exemple : les compteurs d'interface d'un commutateur en SNMPv3 {#example-a-switchs-interface-counters-over-snmpv3}

Un commutateur administrable à 192.168.10.2 répond en SNMPv3 pour l'utilisateur `scada`, configuré sur
le commutateur avec une authentification SHA-256 et une confidentialité AES-128. Lisez le trafic et
l'état de son port 2 :

1. **Ajouter un équipement** ; nommez-le `Core switch`, **Hôte** 192.168.10.2, **Port** 161.
2. Sur la carte **Agent SNMP**, choisissez SNMPv3, saisissez `scada` dans **Utilisateur SNMPv3**,
   gardez **Signé et chiffré (authPriv)**, choisissez SHA-256 dans **Protocole d'authentification** et
   saisissez son mot de passe, gardez AES-128 dans **Protocole de confidentialité** et saisissez son mot
   de passe : chacun celui que le commutateur garde pour `scada`, d'au moins 8 caractères.
3. **Ajouter un tag** `Port 2 in`, **OID** `ifHCInOctets.2`. Le type de donnée devient UInt64, le type
   dans lequel se lit un compteur 64 bits, et la liste ne propose que UInt64, Double et String ;
   **Unité** B.
4. **Ajouter un tag** `Port 2 out`, **OID** `ifHCOutOctets.2`, UInt64, **Unité** B.
5. **Ajouter un tag** `Port 2 state`, **OID** `ifOperStatus.2`, **Type de donnée** Int32 : 1 up,
   2 down, 3 testing, 7 lowerLayerDown.

Le `.2` est l'index de l'interface sur le commutateur, celui que nomme `ifName.2` ; un balayage du
sous-arbre des interfaces liste chaque interface avec son index. La Base URI se lit
`snmp://192.168.10.2:161?version=3&security=authPriv&auth=sha256&priv=aes128&timeoutMs=2000&retries=1`.
Avec les outils, un `opcUaType` dans lequel l'objet ne se lit pas, comme Int32 sur `ifHCOutOctets.2`,
est refusé avec les types dans lesquels il se lit :

```
device_upsert name="Core switch" driver=Snmp host=192.168.10.2 snmpVersion=V3 username=scada password="<authentication password>" snmpSecurityLevel=AuthPriv snmpAuthProtocol=Sha256 snmpPrivacyProtocol=Aes128 snmpPrivacyPassword="<privacy password>"
tag_upsert device="Core switch" name="Port 2 in" address=ifHCInOctets.2 opcUaType=UInt64 unit=B
tag_upsert device="Core switch" name="Port 2 out" address=ifHCOutOctets.2 opcUaType=UInt64 unit=B
tag_upsert device="Core switch" name="Port 2 state" address=ifOperStatus.2 opcUaType=Int32
```

## Outils de l'agent {#agent-tools}

`driver_capabilities` décrit ce pilote sous `snmp` : les versions et les identifiants que prend
chacune, les niveaux de sécurité et les protocoles, le délai de réponse et les nouvelles tentatives,
comment s'écrit un OID, les types par genre de valeur, chaque nom que connaît le pilote avec sa MIB,
son OID et s'il accepte l'écriture, le comportement des lectures et des écritures, la découverte et les
deux exemples ci-dessus. `device_upsert driver=Snmp` prend `host`, `port` (161 par défaut),
`snmpVersion` (`V1`, `V2c`, par défaut, ou `V3`), `snmpCommunity` en SNMPv1 et SNMPv2c (`''`
l'efface), et en SNMPv3 `username` (l'utilisateur), `password` (son mot de passe d'authentification,
d'au moins 8 caractères), `snmpSecurityLevel` (`AuthPriv`, par défaut, `AuthNoPriv` ou
`NoAuthNoPriv`), `snmpAuthProtocol` (`Md5`, `Sha1`, par défaut, `Sha256`, `Sha384` ou `Sha512`),
`snmpPrivacyProtocol` (`Des`, `Aes128`, par défaut, `Aes192` ou `Aes256`) et `snmpPrivacyPassword` ;
avec `responseTimeoutMs` (de 100 à 60000, 2000 par défaut) et `snmpRetries` (de 0 à 5, 1 par
défaut). Une community sur un équipement SNMPv3, ou un champ SNMPv3 sur un équipement à community, est
refusé. Un équipement que les outils renvoient porte `snmp` : la version, `hasCommunity`, le niveau de
sécurité et les protocoles en vigueur, `hasPrivacyPassword`, le délai, les nouvelles tentatives et
`missingCredential`, l'identifiant qu'il attend encore ; aucun secret n'est jamais renvoyé.
`tag_upsert` prend l'OID comme `address` et `opcUaType`, qui vaut par défaut le type dans lequel
l'objet se lit le plus naturellement ; `wireQuantity` et `eipPath` sont refusés.
`device_discover driver=Snmp` parcourt soit `target` (un hôte, avec `port` quand ce n'est pas 161)
avec `snmpVersion` (`V1` ou `V2c`) et `snmpCommunity`, soit `snmpDevice`, le nom d'un équipement du
pilote, seule façon de balayer un agent SNMPv3 ; `snmpSubtrees` choisit les sous-arbres standard
(`System`, `Interfaces`, `Ups`, `Sensors`, `HostResources`, séparés par des virgules) et `snmpSubtree`
en ajoute un. Les outils ne gardent pas la community d'un balayage : un équipement créé à partir de ce
que le balayage a trouvé la reçoit de nouveau dans `device_upsert`, et les tags qui manquent à un
équipement configuré s'ajoutent avec `tag_upsert`. Les autres outils sont sur
[Outils de l'agent](agent-tools).

## Limites à connaître {#limits-worth-knowing}

- Les traps et les informs, ce que l'équipement envoie de lui-même quand quelque chose arrive, ne sont
  pas reçus : chaque valeur est lue à son intervalle de scrutation, si bien qu'une batterie qui faiblit
  se voit à la lecture suivante de son état.
- Aucun fichier MIB n'est importé. Les noms que le pilote connaît sont ceux des MIB standard qu'il
  porte ; un objet de la MIB propre à l'équipement, sous `enterprises`, s'écrit et s'affiche par son
  numéro, et ce qu'il signifie se lit dans la documentation du fabricant.
- La station n'est pas un agent SNMP : rien ne lit la station elle-même en SNMP.
- Un balayage n'atteint un agent SNMPv3 que par un équipement qui garde son utilisateur et ses mots de
  passe, et il n'essaie aucune community ni aucun utilisateur de lui-même.
- Un balayage liste au plus 2000 objets et parcourt pendant au plus 60 secondes : sur un gros
  commutateur, décochez les sous-arbres inutiles, ou nommez celui qui sert.
- Aucun tag n'est un Boolean : un TruthValue ou un marche et arrêt propre à l'équipement se lit en
  Int32.
