SNMP Set Node (#325)

* snmp set node

* updated readme

* readme

* added missing {}

* corrected naming in variables, removed unused ones

* Use snmpObjectType to map types in SnmpSNode

* added varbinds as node property

* edit priority between node and message

* edit help

* updated doc

* try catch JSON.parse§

* corrected typo in html

* Error message in case of JSON parsing error

* removing try/catch on JSON.parse for varbinds, as a wrong varbinds will be
catched/handled in Session.set() method

* edit doc for better presentation
This commit is contained in:
mscbpi 2017-06-27 00:02:34 +02:00 committed by Dave Conway-Jones
parent 6c3c16f210
commit 24b0cd60bb
3 changed files with 253 additions and 91 deletions

View File

@ -34,6 +34,57 @@ want to use `msg.oid` to provide input.
Outputs `msg.payload` containing a table of objects, and the requested `msg.oid`. Outputs `msg.payload` containing a table of objects, and the requested `msg.oid`.
Values depends on the oids being requested. Values depends on the oids being requested.
### snmp-set
SNMP sets the value of one or more OIDs.
`msg.host` may contain the host.
`msg.community` may contain the community.
`msg.varbinds` may contain an array of varbind JSON objects e.g.:
```
msg.varbinds = [
{
"oid": "1.3.6.1.2.1.1.5.0",
"type": "OctetString",
"value": "host1"
}, {
"oid": "1.3.6.1.2.1.1.6.0",
"type": "OctetString",
"value": "somewhere"
}
];
```
Types can be:
* `Boolean`
* `Integer`
* `OctetString`
* `Null`
* `OID`
* `IpAddress`
* `Counter`
* `Gauge`
* `TimeTicks`
* `Opaque`
* `Integer32`
* `Counter32`
* `Gauge32`
* `Unsigned32`
* `Counter64`
* `NoSuchObject`
* `NoSuchInstance`
* `EndOfMibView`
The host configured in the edit config will override `msg.host`. Leave blank if you want to use `msg.host` to provide input.
The community configured in the edit config will override `msg.community`. Leave blank if you want to use `msg.community` to provide input.
The varbinds configured in the edit config will override `msg.varbinds`. Leave blank if you want to use `msg.varbinds` to provide input.
### snmp-table ### snmp-table
Simple SNMP table oid fetcher. Triggered by any input. Simple SNMP table oid fetcher. Triggered by any input.

View File

@ -1,8 +1,7 @@
<script type="text/x-red" data-template-name="snmp"> <script type="text/x-red" data-template-name="snmp">
<div class="form-row"> <div class="form-row">
<label for="node-input-host"><i class="fa fa-globe"></i> Host</label> <label for="node-input-host"><i class="fa fa-globe"></i> Host</label>
<input type="text" id="node-input-host" placeholder="localhost"> <input type="text" id="node-input-host" placeholder="localhost">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-community"><i class="fa fa-user"></i> Community</label> <label for="node-input-community"><i class="fa fa-user"></i> Community</label>
@ -35,33 +34,101 @@
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
RED.nodes.registerType('snmp',{ RED.nodes.registerType('snmp', {
category: 'network-input', category: 'network-input',
color:"YellowGreen", color: "YellowGreen",
defaults: { defaults: {
host: {value:"127.0.0.1"}, host: { value: "127.0.0.1" },
community: {value:"public"}, community: { value: "public" },
version: {value:"1",required:true}, version: { value: "1", required: true },
oids: {value:""}, oids: { value: "" },
name: {value:""} name: { value: "" }
}, },
inputs:1, inputs: 1,
outputs:1, outputs: 1,
icon: "snmp.png", icon: "snmp.png",
label: function() { label: function () {
return this.name||"snmp "+this.host; return this.name || "snmp " + this.host;
}, },
labelStyle: function() { labelStyle: function () {
return this.name?"node_label_italic":""; return this.name ? "node_label_italic" : "";
} }
}); });
</script> </script>
<script type="text/x-red" data-template-name="snmp set">
<div class="form-row">
<label for="node-input-host"><i class="fa fa-globe"></i> Host</label>
<input type="text" id="node-input-host" placeholder="localhost">
</div>
<div class="form-row">
<label for="node-input-community"><i class="fa fa-user"></i> Community</label>
<input type="text" id="node-input-community" placeholder="public">
</div>
<div class="form-row">
<label for="node-input-version"><i class="fa fa-bookmark"></i> Version</label>
<select type="text" id="node-input-version" style="width: 150px;">
<option value="1">v1</option>
<option value="2c">v2c</option>
</select>
</div>
<div class="form-row">
<label for="node-input-varbinds"><i class="fa fa-tags"></i> Varbinds</label>
<textarea rows="10" cols="60" id="node-input-varbinds" placeholder="e.g. [ { &quot;oid&quot;: &quot;1.3.6.1.2.1.1.5.0&quot;,&quot;type&quot;: &quot;OctetString&quot;,&quot;value&quot;: &quot;host1&quot;},{&quot;oid&quot;: &quot;1.3.6.1.2.1.1.6.0&quot;,&quot;type&quot;: &quot;OctetString&quot;,value: &quot;somewhere&quot;}]"
style="width:70%;"></textarea>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/x-red" data-help-name="snmp set">
<p>Simple snmp Set node. Trigger by any input</p>
<p><code>msg.host</code> may contain the host.</p>
<p><code>msg.community</code> may contain the community.</p>
<p><code>msg.varbinds</code> may contain varbinds as an array of json objects containing multiple oids, types and values.
<pre>[
{
"oid": "1.3.6.1.2.1.1.5.0",
"type": "OctetString",
"value": "host1"
},
{ "oid": ... }
]</pre>
</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('snmp set', {
category: 'network-input',
color: "YellowGreen",
defaults: {
host: { value: "127.0.0.1" },
community: { value: "public" },
version: { value: "1", required: true },
varbinds: { value: "" },
name: { value: "" }
},
inputs: 1,
outputs: 0,
icon: "snmp.png",
label: function () {
return this.name || "snmp set " + this.host;
},
labelStyle: function () {
return this.name ? "node_label_italic" : "";
}
});
</script>
<script type="text/x-red" data-template-name="snmp table"> <script type="text/x-red" data-template-name="snmp table">
<div class="form-row"> <div class="form-row">
<label for="node-input-host"><i class="fa fa-globe"></i> Host</label> <label for="node-input-host"><i class="fa fa-globe"></i> Host</label>
<input type="text" id="node-input-host" placeholder="localhost"> <input type="text" id="node-input-host" placeholder="localhost">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-community"><i class="fa fa-user"></i> Community</label> <label for="node-input-community"><i class="fa fa-user"></i> Community</label>
@ -94,32 +161,33 @@
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
RED.nodes.registerType('snmp table',{ RED.nodes.registerType('snmp table', {
category: 'network-input', category: 'network-input',
color:"YellowGreen", color: "YellowGreen",
defaults: { defaults: {
host: {value:"127.0.0.1"}, host: { value: "127.0.0.1" },
community: {value:"public"}, community: { value: "public" },
version: {value:"1",required:true}, version: { value: "1", required: true },
oids: {value:""}, oids: { value: "" },
name: {value:""} name: { value: "" }
}, },
inputs:1, inputs: 1,
outputs:1, outputs: 1,
icon: "snmp.png", icon: "snmp.png",
label: function() { label: function () {
return this.name||"snmp table "+this.host; return this.name || "snmp table " + this.host;
}, },
labelStyle: function() { labelStyle: function () {
return this.name?"node_label_italic":""; return this.name ? "node_label_italic" : "";
} }
}); });
</script> </script>
<script type="text/x-red" data-template-name="snmp subtree"> <script type="text/x-red" data-template-name="snmp subtree">
<div class="form-row"> <div class="form-row">
<label for="node-input-host"><i class="fa fa-globe"></i> Host</label> <label for="node-input-host"><i class="fa fa-globe"></i> Host</label>
<input type="text" id="node-input-host" placeholder="localhost"> <input type="text" id="node-input-host" placeholder="localhost">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-community"><i class="fa fa-user"></i> Community</label> <label for="node-input-community"><i class="fa fa-user"></i> Community</label>
@ -152,34 +220,35 @@
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
RED.nodes.registerType('snmp subtree',{ RED.nodes.registerType('snmp subtree', {
category: 'network-input', category: 'network-input',
color:"YellowGreen", color: "YellowGreen",
defaults: { defaults: {
host: {value:"127.0.0.1"}, host: { value: "127.0.0.1" },
community: {value:"public"}, community: { value: "public" },
version: {value:"1",required:true}, version: { value: "1", required: true },
oids: {value:""}, oids: { value: "" },
name: {value:""} name: { value: "" }
}, },
inputs:1, inputs: 1,
outputs:1, outputs: 1,
icon: "snmp.png", icon: "snmp.png",
label: function() { label: function () {
return this.name||"snmp subtree "+this.host; return this.name || "snmp subtree " + this.host;
}, },
labelStyle: function() { labelStyle: function () {
return this.name?"node_label_italic":""; return this.name ? "node_label_italic" : "";
} }
}); });
</script> </script>
<script type="text/x-red" data-template-name="snmp walker"> <script type="text/x-red" data-template-name="snmp walker">
<div class="form-row"> <div class="form-row">
<label for="node-input-host"><i class="fa fa-globe"></i> Host</label> <label for="node-input-host"><i class="fa fa-globe"></i> Host</label>
<input type="text" id="node-input-host" placeholder="localhost"> <input type="text" id="node-input-host" placeholder="localhost">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-community"><i class="fa fa-user"></i> Community</label> <label for="node-input-community"><i class="fa fa-user"></i> Community</label>
@ -212,24 +281,25 @@
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
RED.nodes.registerType('snmp walker',{ RED.nodes.registerType('snmp walker', {
category: 'network-input', category: 'network-input',
color:"YellowGreen", color: "YellowGreen",
defaults: { defaults: {
host: {value:"127.0.0.1"}, host: { value: "127.0.0.1" },
community: {value:"public"}, community: { value: "public" },
version: {value:"1",required:true}, version: { value: "1", required: true },
oids: {value:""}, oids: { value: "" },
name: {value:""} name: { value: "" }
}, },
inputs:1, inputs: 1,
outputs:1, outputs: 1,
icon: "snmp.png", icon: "snmp.png",
label: function() { label: function () {
return this.name||"snmp walker "+this.host; return this.name || "snmp walker " + this.host;
}, },
labelStyle: function() { labelStyle: function () {
return this.name?"node_label_italic":""; return this.name ? "node_label_italic" : "";
} }
}); });
</script>
</script>

View File

@ -1,39 +1,39 @@
module.exports = function(RED) { module.exports = function (RED) {
"use strict"; "use strict";
var snmp = require("net-snmp"); var snmp = require("net-snmp");
var sessions = {}; var sessions = {};
function getSession(host, community, version){ function getSession(host, community, version) {
var sessionKey = host + ":" + community + ":" + version; var sessionKey = host + ":" + community + ":" + version;
if (!(sessionKey in sessions)){ if (!(sessionKey in sessions)) {
sessions[sessionKey] = snmp.createSession(host, community, {version: version}); sessions[sessionKey] = snmp.createSession(host, community, { version: version });
} }
return sessions[sessionKey]; return sessions[sessionKey];
} }
function SnmpNode(n) { function SnmpNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this, n);
this.community = n.community; this.community = n.community;
this.host = n.host; this.host = n.host;
this.version = (n.version === "2c") ? snmp.Version2c : snmp.Version1; this.version = (n.version === "2c") ? snmp.Version2c : snmp.Version1;
this.oids = n.oids.replace(/\s/g,""); this.oids = n.oids.replace(/\s/g, "");
var node = this; var node = this;
this.on("input",function(msg) { this.on("input", function (msg) {
var host = node.host || msg.host; var host = node.host || msg.host;
var community = node.community || msg.community; var community = node.community || msg.community;
var oids = node.oids || msg.oid; var oids = node.oids || msg.oid;
if (oids) { if (oids) {
getSession(host, community, node.version).get(oids.split(","), function(error, varbinds) { getSession(host, community, node.version).get(oids.split(","), function (error, varbinds) {
if (error) { if (error) {
node.error(error.toString(),msg); node.error(error.toString(), msg);
} }
else { else {
for (var i = 0; i < varbinds.length; i++) { for (var i = 0; i < varbinds.length; i++) {
if (snmp.isVarbindError(varbinds[i])) { if (snmp.isVarbindError(varbinds[i])) {
node.error(snmp.varbindError(varbinds[i]),msg); node.error(snmp.varbindError(varbinds[i]), msg);
} }
else { else {
if (varbinds[i].type == 4) { varbinds[i].value = varbinds[i].value.toString(); } if (varbinds[i].type == 4) { varbinds[i].value = varbinds[i].value.toString(); }
@ -52,14 +52,55 @@ module.exports = function(RED) {
} }
}); });
} }
RED.nodes.registerType("snmp",SnmpNode); RED.nodes.registerType("snmp", SnmpNode);
function SnmpTNode(n) {
RED.nodes.createNode(this,n); function SnmpSNode(n) {
RED.nodes.createNode(this, n);
this.community = n.community; this.community = n.community;
this.host = n.host; this.host = n.host;
this.version = (n.version === "2c") ? snmp.Version2c : snmp.Version1; this.version = (n.version === "2c") ? snmp.Version2c : snmp.Version1;
this.oids = n.oids.replace(/\s/g,""); this.varbinds = n.varbinds;
var node = this;
this.on("input", function (msg) {
var host = node.host || msg.host;
var community = node.community || msg.community;
var varbinds = (node.varbinds) ? JSON.parse(node.varbinds) : msg.varbinds;
if (varbinds) {
for (var i = 0; i < varbinds.length; i++) {
varbinds[i].type = snmp.ObjectType[varbinds[i].type];
}
getSession(host, community, node.version).set(varbinds, function (error, varbinds) {
if (error) {
node.error(error.toString(), msg);
}
else {
for (var i = 0; i < varbinds.length; i++) {
// for version 2c we must check each OID for an error condition
if (snmp.isVarbindError(varbinds[i])) {
node.error(snmp.varbindError(varbinds[i]), msg);
}
}
}
});
}
else {
node.warn("No varbinds to set");
}
});
}
RED.nodes.registerType("snmp set", SnmpSNode);
function SnmpTNode(n) {
RED.nodes.createNode(this, n);
this.community = n.community;
this.host = n.host;
this.version = (n.version === "2c") ? snmp.Version2c : snmp.Version1;
this.oids = n.oids.replace(/\s/g, "");
var node = this; var node = this;
var maxRepetitions = 20; var maxRepetitions = 20;
@ -69,13 +110,13 @@ module.exports = function(RED) {
else { return 0; } else { return 0; }
} }
this.on("input",function(msg) { this.on("input", function (msg) {
var host = node.host || msg.host; var host = node.host || msg.host;
var community = node.community || msg.community; var community = node.community || msg.community;
var oids = node.oids || msg.oid; var oids = node.oids || msg.oid;
if (oids) { if (oids) {
msg.oid = oids; msg.oid = oids;
getSession(host, community, node.version).table(oids, maxRepetitions, function(error, table) { getSession(host, community, node.version).table(oids, maxRepetitions, function (error, table) {
if (error) { if (error) {
node.error(error.toString(), msg); node.error(error.toString(), msg);
} }
@ -110,14 +151,14 @@ module.exports = function(RED) {
} }
}); });
} }
RED.nodes.registerType("snmp table",SnmpTNode); RED.nodes.registerType("snmp table", SnmpTNode);
function SnmpSubtreeNode(n) { function SnmpSubtreeNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this, n);
this.community = n.community; this.community = n.community;
this.host = n.host; this.host = n.host;
this.version = (n.version === "2c") ? snmp.Version2c : snmp.Version1; this.version = (n.version === "2c") ? snmp.Version2c : snmp.Version1;
this.oids = n.oids.replace(/\s/g,""); this.oids = n.oids.replace(/\s/g, "");
var node = this; var node = this;
var maxRepetitions = 20; var maxRepetitions = 20;
var response = []; var response = [];
@ -129,18 +170,18 @@ module.exports = function(RED) {
} }
else { else {
//console.log(varbinds[i].oid + "|" + varbinds[i].value); //console.log(varbinds[i].oid + "|" + varbinds[i].value);
response.push({oid: varbinds[i].oid, value: varbinds[i].value}); response.push({ oid: varbinds[i].oid, value: varbinds[i].value });
} }
} }
} }
this.on("input",function(msg) { this.on("input", function (msg) {
var host = node.host || msg.host; var host = node.host || msg.host;
var community = node.community || msg.community; var community = node.community || msg.community;
var oids = node.oids || msg.oid; var oids = node.oids || msg.oid;
if (oids) { if (oids) {
msg.oid = oids; msg.oid = oids;
getSession(host, community, node.version).subtree(msg.oid, maxRepetitions, feedCb, function(error) { getSession(host, community, node.version).subtree(msg.oid, maxRepetitions, feedCb, function (error) {
if (error) { if (error) {
node.error(error.toString(), msg); node.error(error.toString(), msg);
} }
@ -157,14 +198,14 @@ module.exports = function(RED) {
} }
}); });
} }
RED.nodes.registerType("snmp subtree",SnmpSubtreeNode); RED.nodes.registerType("snmp subtree", SnmpSubtreeNode);
function SnmpWalkerNode(n) { function SnmpWalkerNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this, n);
this.community = n.community; this.community = n.community;
this.host = n.host; this.host = n.host;
this.version = (n.version === "2c") ? snmp.Version2c : snmp.Version1; this.version = (n.version === "2c") ? snmp.Version2c : snmp.Version1;
this.oids = n.oids.replace(/\s/g,""); this.oids = n.oids.replace(/\s/g, "");
var node = this; var node = this;
var maxRepetitions = 20; var maxRepetitions = 20;
var response = []; var response = [];
@ -176,19 +217,19 @@ module.exports = function(RED) {
} }
else { else {
//console.log(varbinds[i].oid + "|" + varbinds[i].value); //console.log(varbinds[i].oid + "|" + varbinds[i].value);
response.push({oid: varbinds[i].oid, value: varbinds[i].value}); response.push({ oid: varbinds[i].oid, value: varbinds[i].value });
} }
} }
} }
this.on("input",function(msg) { this.on("input", function (msg) {
node.msg = msg; node.msg = msg;
var oids = node.oids || msg.oid; var oids = node.oids || msg.oid;
var host = node.host || msg.host; var host = node.host || msg.host;
var community = node.community || msg.community; var community = node.community || msg.community;
if (oids) { if (oids) {
msg.oid = oids; msg.oid = oids;
getSession(host, community, node.version).walk(msg.oid, maxRepetitions, feedCb, function(error) { getSession(host, community, node.version).walk(msg.oid, maxRepetitions, feedCb, function (error) {
if (error) { if (error) {
node.error(error.toString(), msg); node.error(error.toString(), msg);
} }
@ -205,5 +246,5 @@ module.exports = function(RED) {
} }
}); });
} }
RED.nodes.registerType("snmp walker",SnmpWalkerNode); RED.nodes.registerType("snmp walker", SnmpWalkerNode);
}; };