1 ------------------------------------------------------------------------------
3 -- snmp.lua : SNMP primitives
5 ------------------------------------------------------------------------------
7 local snmp
= require
"snmp.core"
10 -- Lua version compatibility
11 local unpack
= unpack
or table.unpack
13 if string.find(_VERSION
, "5.1") then
14 module("snmp", package
.seeall
)
16 _ENV
= setmetatable(snmp
, {
20 ------------------------------------------------------------------------------
21 -- Default Exception Handler
22 ------------------------------------------------------------------------------
25 ------------------------------------------------------------------------------
27 ------------------------------------------------------------------------------
34 ------------------------------------------------------------------------------
35 -- Init Mibs and SNMP client
36 ------------------------------------------------------------------------------
37 if (LUA_SNMP_MIBS
== nil or LUA_SNMP_MIBS
) then
41 ------------------------------------------------------------------------------
43 ------------------------------------------------------------------------------
44 function mib
.renums(oid
)
45 local t
, err
= mib
.enums(oid
)
46 if not t
then return nil, err
end
48 for k
, v
in ipairs(t
) do
54 ------------------------------------------------------------------------------
55 -- Assemble list of net-snmp config files
56 ------------------------------------------------------------------------------
57 local function configfiles()
62 os
.getenv("HOME").."/.snmp/"
70 local confpath
= os
.getenv("SNMPCONFPATH")
72 for dir
in string.gmatch(confpath
, "[^:]+") do
73 table.insert(t
, dir
.. "/snmp.conf")
74 table.insert(t
, dir
.. "/snmp.local.conf")
75 table.insert(t
, dir
.. "/snmpapp.conf")
78 for _
, dir
in ipairs(dirlist
) do
79 for _
, file
in ipairs(filelist
) do
80 table.insert(t
, dir
.. file
)
88 ------------------------------------------------------------------------------
89 -- Gather SNMP configuration
90 ------------------------------------------------------------------------------
91 local function read_config()
93 for _
, fname
in ipairs(configfiles()) do
94 local f
= io
.open(fname
, "r")
96 for line
in f
:lines() do
97 tok
, val
= string.gsub(line
, "^%s*(#*)%s*(%w+)%s+([^%s#]*)",
98 function(comment1
, tok
, val
)
99 if comment1
~= "#" then
100 -- Uncomment to see which token read from which file.
101 -- print(string.format("config-read: %s = %s from %s",
113 config
= read_config()
119 ------------------------------------------------------------------------------
120 -- A metatable for variable bindings.
121 ------------------------------------------------------------------------------
123 __tostring
= sprint_variable
,
124 __eq
= function(vb1
, vb2
) return vb1
.value
== vb2
.value
end,
125 __le
= function(vb1
, vb2
) return vb1
.value
<= vb2
.value
end,
126 __lt
= function(vb1
, vb2
) return vb1
.value
< vb2
.value
end,
127 __concat
= function(vb1
, vb2
)
129 if vb1
.oid
and vb2
.oid
then return {vb1
, vb2
} end
131 for _
, v
in ipairs(vb1
) do table.insert(vb
, v
) end
133 table.insert(vb
, vb2
)
135 for _
, v
in ipairs(vb2
) do table.insert(vb
, v
) end
138 table.insert(vb
, vb1
)
139 for _
, v
in ipairs(vb2
) do table.insert(vb
, v
) end
145 ------------------------------------------------------------------------------
146 -- Init general things and config tokens
147 ------------------------------------------------------------------------------
148 assert(not init(tokens
, function(token
, line
)
151 ------------------------------------------------------------------------------
152 -- Init Traps handler.
153 -- 1. LUASNMP_STRAPS is set: use straps
154 -- 2. LUASNMP_TRAPDPORT is set: use LUASNMP_TRAPDPORT
155 -- 3. trapdPort in snmp.conf is set: use configuration value
157 ------------------------------------------------------------------------------
158 local trapdport
= tonumber(os
.getenv("LUASNMP_TRAPDPORT") or
159 config
.trapdPort
) or 6000
165 ------------------------------------------------------------------------------
166 -- Session configuration parameters
167 ------------------------------------------------------------------------------
178 ["noAuthNoPriv"] = NOAUTH
,
179 ["authNoPriv"] = AUTHNOPRIV
,
180 ["authPriv"] = AUTHPRIV
187 ------------------------------------------------------------------------------
188 -- SNMPv3 transform OIDs
189 -- Giving them here explicitly avoids the necessity to load the MIBs.
190 ------------------------------------------------------------------------------
192 NoAuth
= "1.3.6.1.6.3.10.1.1.1",
193 HMACMD5Auth
= "1.3.6.1.6.3.10.1.1.2",
194 HMACSHA1Auth
= "1.3.6.1.6.3.10.1.1.3",
195 NoPriv
= "1.3.6.1.6.3.10.1.2.1",
196 DESPriv
= "1.3.6.1.6.3.10.1.2.2",
197 AESPriv
= "1.3.6.1.6.3.10.1.2.4"
201 auth
= "1.3.6.1.6.3.15.1.2.2.1.6",
202 ownAuth
= "1.3.6.1.6.3.15.1.2.2.1.7",
203 priv
= "1.3.6.1.6.3.15.1.2.2.1.9",
204 ownPriv
= "1.3.6.1.6.3.15.1.2.2.1.10"
208 userStatus
= "1.3.6.1.6.3.15.1.2.2.1.13",
209 userSecurityName
= "1.3.6.1.6.3.15.1.2.2.1.3",
210 userCloneFrom
= "1.3.6.1.6.3.15.1.2.2.1.4"
214 groupName
= "1.3.6.1.6.3.16.1.2.1.3",
215 sec2GroupStorageType
= "1.3.6.1.6.3.16.1.2.1.4",
216 sec2GroupStatus
= "1.3.6.1.6.3.16.1.2.1.5",
217 accessContextMatch
= "1.3.6.1.6.3.16.1.4.1.4",
218 accessReadViewName
= "1.3.6.1.6.3.16.1.4.1.5",
219 accessWriteViewName
= "1.3.6.1.6.3.16.1.4.1.6",
220 accessNotifyViewName
= "1.3.6.1.6.3.16.1.4.1.7",
221 accessStorageType
= "1.3.6.1.6.3.16.1.4.1.8",
222 accessStatus
= "1.3.6.1.6.3.16.1.4.1.9",
223 viewTreeFamilyMask
= "1.3.6.1.6.3.16.1.5.2.1.3",
224 viewTreeFamilyType
= "1.3.6.1.6.3.16.1.5.2.1.4",
225 viewTreeFamilyStorageType
= "1.3.6.1.6.3.16.1.5.2.1.5",
226 viewTreeFamilyStatus
= "1.3.6.1.6.3.16.1.5.2.1.6"
236 ------------------------------------------------------------------------------
238 ------------------------------------------------------------------------------
251 INCONSISTENTVALUE
= 12
252 RESOURCEUNAVAILABLE
= 13
255 AUTHORIZATIONERROR
= 16
257 INCONSISTENTNAME
= 18
274 BADPRIVPASSPHRASE
= 116
294 ------------------------------------------------------------------------------
296 ------------------------------------------------------------------------------
298 errtb
[0] = "snmp: no error"
299 errtb
[1] = "snmp: too big"
300 errtb
[2] = "snmp: no such name"
301 errtb
[3] = "snmp: bad value"
302 errtb
[4] = "snmp: read only"
303 errtb
[5] = "snmp: generic error"
304 errtb
[6] = "snmp: no access"
305 errtb
[7] = "snmp: wrong type"
306 errtb
[8] = "snmp: wrong length"
307 errtb
[9] = "snmp: wrong encoding"
308 errtb
[10] = "snmp: wrong value"
309 errtb
[11] = "snmp: no creation"
310 errtb
[12] = "snmp: inconsistent value"
311 errtb
[13] = "snmp: resource unavailable"
312 errtb
[14] = "snmp: commit failed"
313 errtb
[15] = "snmp: undo failed"
314 errtb
[16] = "snmp: authorization error"
315 errtb
[17] = "snmp: not writable"
316 errtb
[18] = "snmp: inconsistent name"
318 local cnf_err
= "snmp: invalid session configuration "
319 errtb
[101] = cnf_err
.."(version)"
320 errtb
[102] = cnf_err
.."(community)"
321 errtb
[103] = cnf_err
.."(timeout)"
322 errtb
[104] = cnf_err
.."(retries)"
323 errtb
[105] = cnf_err
.."(peer address)"
324 errtb
[106] = cnf_err
.."(port)"
325 errtb
[107] = cnf_err
.."(callback)"
326 errtb
[108] = cnf_err
.."(trap)"
327 errtb
[109] = cnf_err
.."(inform)"
328 local opt_err
= "snmp: invalid configuration for SNMPv1 session "
329 errtb
[110] = opt_err
.."(inform)"
330 errtb
[111] = cnf_err
.."(sprintvar)"
331 errtb
[112] = cnf_err
.."(sprintval)"
332 errtb
[113] = cnf_err
.."(user)"
333 errtb
[114] = cnf_err
.."(securityLevel)"
334 errtb
[115] = cnf_err
.."(authPassphrase, password)"
335 errtb
[116] = cnf_err
.."(privPassphrase, password)"
336 errtb
[117] = cnf_err
.."(engineBoots)"
337 errtb
[118] = cnf_err
.."(engineTime)"
338 errtb
[119] = opt_err
.."(includeroot)"
340 errtb
[120] = "snmp: invalid session"
341 errtb
[121] = "snmp: invalid variable type"
342 errtb
[122] = "snmp: invalid variable name"
344 errtb
[123] = "snmp: invalid argument (non-repeaters)"
345 errtb
[124] = "snmp: invalid argument (max-repetitions)"
347 errtb
[125] = "snmp: invalid operation for SNMPv1 session (inform)"
348 errtb
[126] = "snmp: invalid argument (trap OID)"
350 errtb
[190] = "snmp: no response (timeout)"
351 errtb
[191] = "snmp: internal failure"
352 errtb
[192] = "snmp: bad argument"
353 errtb
[193] = "snmp: oid not increasing"
354 errtb
[194] = "snmp: engineID probe failed"
355 errtb
[195] = "snmp: bad security model"
356 errtb
[196] = "snmp: bad security name"
357 errtb
[197] = "snmp: bad group name"
359 ------------------------------------------------------------------------------
360 -- Returns nil + error message in case of errors.
361 -- @param errnum number - Error number.
362 -- @param message string - function's message to append.
363 -- @return nil, "errormsg (MESSAGE)"
364 ------------------------------------------------------------------------------
365 local function FAIL(err
, message
)
367 if type(err
) == "number" then
369 elseif type(err
) == "string" then
373 rmsg
= rmsg
.. " (" .. message
..")"
378 ------------------------------------------------------------------------------
380 ------------------------------------------------------------------------------
387 ------------------------------------------------------------------------------
389 ------------------------------------------------------------------------------
407 TYPE_NSAPADDRESS
= 13
412 TYPE_SIMPLE_LAST
= 16
425 TYPE_UNSIGNED64
= 123
427 ------------------------------------------------------------------------------
429 ------------------------------------------------------------------------------
453 "NOTIFICATION-GROUP",
455 "AGENT-CAPABILITIES",
459 typetb
[120] = "Opaque: Float"
460 typetb
[121] = "Opaque: Double"
461 typetb
[122] = "Opaque: Integer64"
462 typetb
[123] = "Opaque: Unsigned64"
464 typetb
[128] = "NO SUCH OBJECT"
465 typetb
[129] = "NO SUCH INSTANCE"
466 typetb
[130] = "END OF MIB VIEW"
468 ------------------------------------------------------------------------------
470 ------------------------------------------------------------------------------
472 ------------------------------------------------------------------------------
473 -- Return comprimated varlist result.
474 -- @param vl table - Varlist.
475 -- @param err string - error or nil.
476 -- @param errindex number - index of failure varbind in varlist.
477 -- @return varlist or nil + errormessage on failure.
478 ------------------------------------------------------------------------------
479 local function retvarlist(vl
, err
, errindex
)
482 return FAIL(err
, "in index " .. tostring(errindex
))
492 ------------------------------------------------------------------------------
493 -- Print an object value
494 -- @param vb Variable binding or value.
495 -- @return formatted string for printing.
496 ------------------------------------------------------------------------------
497 function sprintval2(vb
)
498 if type(vb
) ~= "table" then
505 local value
= vb
.value
510 if type == TYPE_TIMETICKS
then
511 local days
,hours
,minutes
,seconds
,deci
,ticks
512 if (value
.days
) then days
= value
.days
else days
= 0 end
513 if (value
.hours
) then hours
= value
.hours
else hours
= 0 end
514 if (value
.minutes
) then minutes
= value
.minutes
else minutes
= 0 end
515 if (value
.seconds
) then seconds
= value
.seconds
else seconds
= 0 end
516 if (value
.deciseconds
) then deci
= value
.deciseconds
else deci
= 0 end
517 if (value
.ticks
) then ticks
= value
.ticks
else ticks
= 0 end
518 return string.format("%dd %d:%d:%d.%d (%d)",days
,hours
,minutes
,seconds
,deci
,ticks
)
519 elseif (type == TYPE_INTEGER
) or (type == TYPE_UINTEGER
) then
520 local enums
= mib
.enums(vb
.oid
)
521 if enums
and enums
[value
] then
522 return enums
[value
].."("..value
..")"
524 elseif (type == TYPE_OBJID
) then
525 local name
= mib
.name(value
)
526 if name
~= value
then
527 return name
.." ("..value
..")"
532 return tostring(value
)
535 ------------------------------------------------------------------------------
536 -- Print an object variable.
537 -- @param vb table - Variable binding.
538 -- @return Formatted string for printing.
539 ------------------------------------------------------------------------------
540 function sprintvar2(vb
)
541 if type(vb
) ~= "table" then
542 return "<Invalid varbind>"
544 local name
= mib
.name(vb
.oid
) ---> aceitar ja' receber nome pronto?
548 return string.format("%s (%s) = %s",name
,sprint_type(vb
.type),sprintval2(vb
))
551 ------------------------------------------------------------------------------
552 -- Print an object type.
553 -- @param t Variable binding or type code.
554 -- @return Formatted string for printing.
555 ------------------------------------------------------------------------------
556 function sprint_type(t
)
558 if type(t
) == "table" then
559 tCode
= tonumber(t
.type or mib
.type(t
.oid
))
560 elseif type(t
) == "number" then
562 elseif type(t
) == "string" then
565 if tCode
and typetb
[tCode
] then
568 return "<Invalid type>"
573 mib
.typename
= sprint_type
575 ------------------------------------------------------------------------------
577 -- @param err Error code.
578 -- @return Formatted string for printing.
579 ------------------------------------------------------------------------------
580 function sprint_error(err
)
581 local str
= errtb
[err
]
585 return "UNKNOWN ERROR"
589 ------------------------------------------------------------------------------
591 -- Does not check whether OID is in the tree.
592 -- @param oid string - OID string representation.
593 -- @return OID string, if o.k. Nil otherwise.
594 ------------------------------------------------------------------------------
595 local function isoid(oid
)
596 if type(oid
) ~= "string" then return FAIL(BADARG
) end
597 if string.find(string.gsub(oid
,"%.%d%d*",""),"^%d%d*$") then
600 return FAIL("snmp: not an OID")
604 ------------------------------------------------------------------------------
605 -- Eval length of an OID.
606 -- Does not check whether OID is in the tree.
607 -- @param oid string - OID string representation.
608 -- @return OID string, if o.k. Nil otherwise.
609 ------------------------------------------------------------------------------
610 local function oidlen(oid
)
611 local oid
, err
= isoid(oid
)
612 if not oid
then return FAIL("snmp: not an OID") end
614 string.gsub(oid
, "%.", function(v
)
620 ------------------------------------------------------------------------------
621 -- Eval a base OID of certain length.
622 -- Does not check whether OID is in the tree.
623 -- @param oid string - OID string representation.
624 -- @param len number - Length of base OID.
625 -- @return Base OID string, if o.k. nil otherwise.
626 ------------------------------------------------------------------------------
627 local function oidbase(oid
, len
)
629 local len
= len
or oidlen(oid
)
630 oid
, err
= isoid(oid
)
631 if not oid
then return nil, err
end
633 for d
, p
in string.gmatch(oid
,"(%d+)(%.*)") do
642 print("###", oid
, rv
)
646 ------------------------------------------------------------------------------
647 -- Translate an OID into a table.
648 -- Does not check whether OID is in the tree.
649 -- @param oid string - OID string representation or name.
650 -- @return Table presentation of an OID: {1,2,17,2,3}.
651 ------------------------------------------------------------------------------
652 local function oidtotable(oid
)
654 oid
, err
= isoid(oid
)
655 if not oid
then return nil, err
end
657 string.gsub(oid
, "(%d+)%.*", function(d
) table.insert(t
, tonumber(d
)) end)
661 ------------------------------------------------------------------------------
663 -- Does not check whether OID is in the tree.
664 -- @param oid1 string - OID string 1 or name 1.
665 -- @param oid2 string - OID string 2 or name 2.
666 -- @return 1 if oid1 > oid2, 0 if oid1 == oid2, -1 if oid1 < oid2.
667 ------------------------------------------------------------------------------
668 local function oidcompare(oid1
, oid2
)
669 if not isoid(oid1
) then return FAIL(BADARG
, "oid1") end
670 if not isoid(oid2
) then return FAIL(BADARG
, "oid2") end
671 local t1
,n1
= oidtotable(oid1
)
672 local t2
,n2
= oidtotable(oid2
)
679 if t1
[i
] > t2
[i
] then
681 elseif t1
[i
] < t2
[i
] then
685 if n1
< n2
then return -1 end
686 if n2
< n1
then return 1 end
690 ------------------------------------------------------------------------------
691 -- Returns the index of a varbind based on a superordinated OID.
692 -- @param vb table - Variable name (text or OID).
693 -- @param tname string - Super-ordinated OID
694 -- @return Index as string.
695 ------------------------------------------------------------------------------
696 local function oidindex(oid
, base
)
697 if not isoid(oid
) then return FAIL(BADARG
, "oid") end
698 if not isoid(base
) then return FAIL(BADARG
, "base") end
699 local s
, n
= string.gsub(oid
, "^"..base
.."%.(.+)","%1")
700 if n
> 0 then return s
else return "" end
703 ------------------------------------------------------------------------------
705 -- Search in all directories given by MIBDIRS.
706 -- @param fname string File name.
707 ------------------------------------------------------------------------------
708 local function load(fname
)
709 if string.sub(fname
, 1, 1) == "/" then
710 local tree
, err
= mib
._load(fname
)
711 if tree
then return tree
end
713 local configdirs
= string.gsub(config
.mibdirs
or "", "(%+*)(.+)", "%2")
714 local mibdirs
= ".:" .. (os
.getenv("LUASNMP_MIBDIRS") or os
.getenv("MIBDIRS") or configdirs
)
715 for dir
in string.gmatch(mibdirs
, "[^:;]+") do
716 for _
,ext
in ipairs
{".txt","",".mib"} do
717 local fn
= dir
.."/"..fname
..ext
718 local f
= io
.open(fn
,"r")
721 local tree
, err
= mib
._load(fn
)
722 if tree
then return tree
end
727 return nil, "mib: cannot add mib"
732 mib
.oidbase
= oidbase
733 mib
.oidtotable
= oidtotable
734 mib
.oidcompare
= oidcompare
735 mib
.oidindex
= oidindex
738 -- Some other names for sprints.
739 sprintval
= sprint_value
740 sprinttype
= sprint_type
741 sprintvar
= sprint_variable
742 sprinterr
= sprint_error
743 ---------------------------------------------------------------------------
745 -- @param sess table - Session.
746 -- @param var table or string - Root object.
747 -- @return Varbind list with values.
748 ---------------------------------------------------------------------------
749 function walk(sess
, var
)
754 -- if not sess then return nil, errtb[BADSESSION] end
755 if not sess
then return FAIL(BADSESSION
) end
756 local var
= var
or "mib-2"
757 if type(var
) == "table" then
758 oid
= mib
.oid(var
.oid
)
759 elseif type(var
) == "string" then
762 return FAIL(BADARG
, "var")
764 if not oid
then return nil, errtb
[BADOID
] end
766 if sess
.includeroot
then
767 vb
, err
= sess
:get(root
)
768 if err
then return nil, err
end
771 local rootlen
= oidlen(root
.oid
)
773 local rootoid
= root
.oid
776 vb
, err
= sess
:getnext(vb
)
777 if not vb
then return nil, err
end
779 if err
== NOSUCHNAME
or string.find(err
, "no such name") then
787 if oidlen(oid
) < rootlen
or
788 vb
.type == ENDOFMIBVIEW
or
789 not string.find(oid
, rootoid
) then
792 if oidcompare(last
, oid
) >= 0 then
793 return nil, errtb
[BADOID
]
799 if not err
and #t
== 0 then
800 vb
, err
= sess
:get(root
)
801 if err
then return t
, err
end
807 ---------------------------------------------------------------------------
808 -- Retrieve sorted list of keys of a table
809 ---------------------------------------------------------------------------
812 for k
,v
in pairs(t
) do
819 ---------------------------------------------------------------------------
820 -- Sorted iteration over a list of keys in table.
821 ---------------------------------------------------------------------------
822 assert(not _G
.spairs
, "Symbol 'spairs' already defined")
823 function _G
.spairs(t
)
824 local keys
= getkeys(t
)
829 return keys
[i
], t
[keys
[i]]
832 ---------------------------------------------------------------------------
833 -- Convert formatted time value to varbind.
834 -- @param s string - Formatted string.
836 ---------------------------------------------------------------------------
837 function uptimeS2V(s
)
839 if type(s
) ~= "string" then return FAIL(BADARG
) end
840 string.gsub(s
, "(%d+):(%d+):(%d+):(%d+)%.(%d+)$",
841 function(d
, h
, m
, s
, ds
)
843 days
= tonumber(d
) or 0,
844 hours
= tonumber(h
) or 0,
845 minutes
= tonumber(m
) or 0,
846 seconds
= tonumber(s
) or 0,
847 deciseconds
= tonumber(ds
) or 0
849 ticks
.ticks
= ticks
.deciseconds
+
850 ticks
.seconds
* 100 +
851 ticks
.minutes
* 60 * 100 +
852 ticks
.hours
* 60 * 60 * 100 +
853 ticks
.days
* 24 * 60 * 60 * 100
858 ---------------------------------------------------------------------------
859 -- Convert uptime varbind to string.
860 -- @param vb table - Varbinding containing sysUpTime.
861 -- @return Formatted string.
862 ---------------------------------------------------------------------------
863 function uptimeV2S(vb
)
864 if type(vb
) ~= "table" then return FAIL(BADARG
) end
865 return string.format("%d:%d:%d:%d.%d",
866 vb
.days
, vb
.hours
, vb
.minutes
,
867 vb
.seconds
, vb
.deciseconds
)
870 ---------------------------------------------------------------------------
871 -- A generic trap handler.
872 -- Only activated if a user supplied trap callback function has
873 -- been provided. It also calls the user callback function.
874 -- NOTE: The scanner of the trap message requires the following log formats
875 -- settings in snmptrapfmt.conf to work properly:
878 -- VARFMT="#[%s] %n (%t) : %v"
879 -- LOGFMT="$x#$A#$e#$G#$S#$T$*"
880 -- @param session table - Session that captures the trap.
881 -- @param msg string - Message from snmptrapd.
882 -- See snmptrapd.conf manual page for content.
884 ---------------------------------------------------------------------------
885 function __trap(session
, msg
)
886 local host
, src
, vbs
, sip
, dip
, sport
, dport
, uptimeName
, uptimeVal
, vbs
, ip
, port
887 -- debugging: uncomment if desired
888 --print(string.format(" session.name=%s", session.name))
889 --print(string.format(" generic_trap(): msg = %q", msg))
890 --print(string.format(" netsnmp version: %s", snmp.getversion()))
891 --print(string.format(" snmp._SYSTEM: %s", snmp._SYSTEM))
893 -- The message may ne different for Cygwin and Linux.
894 -- We keep the differentiation even if not really required.
895 if snmp
._SYSTEM
== "Cygwin" and snmp
.getversion() > "5.3" then
897 "^%s*([%w%.]+)%s+(%w+):%s*%[[%d%.]+%]%-%>%[([%d%.]+)%]:(%d+)%s+([^%s]+)%s+([^%s]+)%s+(.*)",
899 host
, proto
, ip
, port
, uptimeName
, uptimeVal
, vbs
= select(1, ...)
902 -- print(string.format(" host=%q, proto=%q, ip=%q, port=%q, uptimeName=%q, uptimeVal=%q, vbs=%q",
903 -- host, proto, ip, port, uptimeName, uptimeVal, vbs))
904 elseif snmp
.getversion() > "5.5" then
907 -- " localhost UDP: [127.0.0.1]->[127.0.0.1]:-6577 \
908 -- iso.3.6.1.2.1.1.3.0 0:2:11:01.53 iso.3.6.1.6.3.1.1.4.1.0 ccitt.0 iso.3.6.1.2.1.1.5.0 \"hello\""
909 "^%s*([%w%.]+)%s+(%w+):%s*%[([%d%.]+)%]:([%d]+)%-%>%[([%d%.]+)%]:([%-%d]+)%s+([^%s]+)%s+([^%s]+)%s+(.*)",
911 host
, proto
, sip
, sport
, dip
, dport
, uptimeName
, uptimeVal
, vbs
= select(1, ...)
915 -- print("dissected msg:", host, proto, sip, sport, dip, dport, uptimeName, uptimeVal, vbs)
917 -- debugging: uncomment if desired
918 -- print(string.format(" host=%q, proto=%q, ip=%q, port=%q, uptimeName=%q, uptimeVal=%q, vbs=%q",
919 -- host, proto, ip, port, uptimeName, uptimeVal, vbs))
921 string.gsub(msg
, "([%w%.]+)%s+([%d%.]+)%s+([^%s]+)%s+([^%s]+)%s+(.*)",
923 local arg
= {select(1, ...)}
927 uptimeVal
= uptimeS2V(arg
[4])
931 if dip
== session
.peer_ip
or true then
932 -- Convert variable bindings
934 if string.find(snmp
.getversion(), "5.4") then
935 vlist
= {{oid
= uptimeName
, type = mib
.type("sysUpTime"), value
= uptimeVal
}}
936 elseif string.find(snmp
.getversion(), "5.3") then
937 -- Note: we don't get a reasonable type value for sysUpTimeInstance in net-snmp 5.3
938 vlist
= {{oid
=uptimeName
, type=mib
.type("sysUpTime"), value
= uptimeVal
}}
940 vlist
= {{oid
=uptimeName
, type=mib
.type(uptimeName
), value
= uptimeVal
}}
942 string.gsub(vbs
, "([^%s]+)%s+([^%s]+)%s*",
945 local typ
= mib
.type(name
)
946 local value
= mib
.oid(val
) or uptimeS2V(val
) or val
947 table.insert(vlist
, {oid
=oid
, type=typ
, value
=value
})
950 -- table.foreach(vlist, function(k,v) table.foreach(v, print) end)
951 session
.usertrap(vlist
, ip
, port
, host
, session
)
956 ---------------------------------------------------------------------------
957 -- Create a new variable binding.
958 -- @param name string - Name or OID of variable.
959 -- @param value any - Value of variable.
960 -- @param type number (opt) - Type of the object.
961 -- @return Variable binding with metamethods set.
962 ---------------------------------------------------------------------------
963 function newvar(name
, value
, typ
, session
)
964 local oid
= mib
.oid(name
) or name
965 local vb
= {oid
= oid
, type = typ
or mib
.type(oid
), value
= value
}
966 if session
then vb
[".session"] = session
end
967 setmetatable(vb
, __vbindmetatable
)
971 ---------------------------------------------------------------------------
972 -- Print a hexstring (key) in the form 0x1234etc.
973 -- @param key string - Hexstring (may contain embedded zeros).
974 -- @param len number - Length of the (sub)string to evaluate.
975 -- @return String containing a readable presentation of the hexstring.
976 ---------------------------------------------------------------------------
977 function sprintkeyx(key
, len
)
979 local slen
= string.len(key
)
980 local len
= len
or slen
981 if len
> slen
then len
= slen
end
983 s
= s
..string.format("%02X", string.byte(key
, i
))
988 ---------------------------------------------------------------------------
989 -- Print a hexstring (key) in the OID form 1.2.3.4.
990 -- @param key string - Hexstring (may contain embedded zeros).
991 -- @param len number - Length of the (sub)string to evaluate.
992 -- @return String containing an OID presentation of the input string.
993 ---------------------------------------------------------------------------
994 function sprintkeyd(key
, len
)
996 local slen
= string.len(key
)
997 local len
= len
or slen
998 if len
> slen
then len
= slen
end
1000 s
= s
..string.format("%d", string.byte(key
,i
))
1001 if i
< len
then s
= s
.. "." end
1006 ---------------------------------------------------------------------------
1007 -- Print a hexstring (key) in the form 01:02:03:etc.
1008 -- @param key string - Hexstring (may contain embedded zeros).
1009 -- @param len number - Length of the (sub)string to evaluate.
1010 -- @return String containing a presentation of the hexstring that can
1011 -- be evaluated by snmp.set(SESSION, VAR)
1012 ---------------------------------------------------------------------------
1013 function sprintkey(key
, len
)
1014 local slen
= string.len(key
)
1015 local len
= len
or slen
1017 if len
> slen
then len
= slen
end
1019 s
= s
..string.format("%02x", string.byte(key
, i
))
1020 if i
< len
then s
= s
.. ":" end
1026 -- Shortcuts - probably more SNMP like names.
1028 key2oid
= sprintkeyd
1029 key2hex
= sprintkeyx
1030 key2octet
= sprintkey
1031 octetstring
= sprintkey
1032 hexstring
= sprintkeyx
1034 ---------------------------------------------------------------------------
1035 -- Print a string as OID. The length is prepended to the OID string
1036 -- representing the actual string data.
1037 -- @param str string - String to convert.
1038 -- @return String containint an OID in the from LENGTH.CHAR.CHAR.etc.
1039 ---------------------------------------------------------------------------
1040 function stringoid(str
)
1041 local len
= string.len(str
)
1045 return string.format("%d.%s", string.len(str
), key2oid(str
))
1049 mib
.stringoid
= stringoid
1050 ---------------------------------------------------------------------------
1051 -- Create an index in OID from from the given parameters.
1052 -- @param arg table - Table containing a variable number of parameters
1053 -- @return String containing the index as OID.
1054 ---------------------------------------------------------------------------
1055 function instance(...)
1057 arg
= {select(1, ...)}
1058 for k
,v
in ipairs(arg
) do
1059 if type(v
) == "number" then
1060 oid
= oid
.. string.format(".%d", v
)
1061 elseif type(v
) == "string" then
1063 oid
= oid
.. string.format(".%d.%s",oidlen(v
), v
)
1065 oid
= oid
.. string.format(".%s", stringoid(v
))
1067 elseif type(v
) == "boolean" then
1068 if v
== true then oid
= oid
.. ".1" else
1069 oid
= oid
.. ".0" end
1070 elseif type(v
) == "table" then
1071 oid
= oid
.. instance(unpack(v
))
1073 return FAIL(BADARG
, "arg["..k
.."]")
1080 mib
.instance
= instance
1082 ------------------------------------------------------------------------------
1083 -- Change user's password.
1084 -- @param session table - Active session.
1085 -- @param oldpw string - Old password.
1086 -- @param newpw string - New password.
1087 -- @param flag string (opt) - Indicates what pass phrase to
1088 -- change: "a" = auth, "ap" = auth + priv, "p" = priv.
1089 -- @param user (opt) string - What user to change.
1090 -- @param engineID (opt) hexstring - Context engine ID to use.
1091 -- @return varlist on success, nil + error message of failure.
1092 ------------------------------------------------------------------------------
1093 function newpassword(session
, oldpw
, newpw
, flag
, user
, engineID
)
1094 local authKeyChange
, privKeyChange
1096 local doauth
, dopriv
= false, false
1097 -- Be sure we run a version 3 session
1098 -- Do we really need this? Don't think so (leu)
1099 if session
.version
~= SNMPv3
then return FAIL(BADSESSION
) end
1101 -- What to change: auth=a, priv=p or both=ap
1103 if string.find(flag
,"a") then doauth
= true end
1104 if string.find(flag
,"p") then dopriv
= true end
1106 -- What user to change
1109 authKeyChange
= keyOid
.ownAuth
1110 privKeyChange
= keyOid
.ownPriv
1114 if type(user
) ~= "string" then
1115 return nil, errtb
[BADARG
] .. " (user)"
1117 authKeyChange
= keyOid
.auth
1118 privKeyChange
= keyOid
.priv
1121 if not engineID
then
1122 local t
= session
:details()
1123 if t
.contextEngineIDLen
== 0 then
1124 -- we need an engineID and don't have one: probe with empty get-request
1125 local vb
, err
= session
:get(nil)
1126 if not vb
or err
then return nil, errtb
[BADENGPROBE
] end
1128 t
= session
:details()
1129 engineID
= t
.contextEngineID
1131 -- check password lengths
1132 if type(oldpw
) ~= "string" and string.len(oldpw
) < 8 then
1133 return FAIL(BADARG
, "oldpw")
1135 if type(newpw
) ~= "string" and string.len(oldpw
) < 8 then
1136 return FAIL(BADARG
, "newpw")
1139 -- create old and new keys
1141 if session
.authType
== "MD5" then
1142 authProto
= usmProtocol
.HMACMD5Auth
1144 authProto
= usmProtocol
.HMACSHA1Auth
1146 local oldKu
, oldKuLen
= createkey(session
, oldpw
, authProto
)
1147 if not oldKu
then return nil, oldKuLen
end
1148 local newKu
, newKuLen
= createkey(session
, newpw
, authProto
)
1149 if not newKu
then return nil, newKuLen
end
1151 -- create old and new localized keys
1152 local oldKul
, oldKulLen
= createlocalkey(session
, oldKu
, authProto
, engineID
)
1153 if not oldKul
then return nil, oldKulLen
end
1154 local newKul
, newKulLen
= createlocalkey(session
, newKu
, authProto
, engineID
)
1155 if not newKul
then return nil, newKulLen
end
1159 if session
.privType
== "DES" or session
.privType
== "AES" then
1160 oldKulPrivLen
, newKulPrivLen
= 16, 16
1166 -- create keychange string
1167 local keychg
, keychgpriv
, keychglen
, keychgprivlen
1169 keychg
, keychglen
= keychange(session
, oldKul
, newKul
, authProto
)
1170 if not keychg
then return FAIL("snmp: cannot create keychange") end
1174 keychgpriv
, keychgprivlen
= keychange(session
, oldKulPriv
, newKulPriv
, authProto
)
1175 if not keychgpriv
then return FAIL("snmp: cannot create keychange priv") end
1178 -- setup varbind list
1181 local vb
= newvar(string.format("%s.%d.%s.%d.%s",
1183 string.len(engineID
), key2oid(engineID
),
1184 string.len(user
), key2oid(user
)),
1185 key2octet(keychg
, keychglen
),
1187 table.insert(vl
, vb
)
1190 local vb
= newvar(string.format("%s.%d.%s.%d.%s",
1192 string.len(engineID
), key2oid(engineID
),
1193 string.len(user
), key2oid(user
)),
1194 key2octet(keychgpriv
, keychgprivlen
),
1198 vl
, err
, errindex
= session
:set(vl
)
1201 return FAIL(err
,"index " .. tostring(errindex
))
1210 ------------------------------------------------------------------------------
1211 -- Create user and optionally take authentication parameters
1212 -- from another user.
1213 -- @param session table - Session for performing the operation.
1214 -- @param user string - Name of user to create.
1215 -- @param clonefrom string (opt) - Name of user to clone.
1216 -- @return Varlist or nil + errormessage
1217 ------------------------------------------------------------------------------
1218 function createuser(session
, user
, clonefrom
, engineID
)
1221 if type(user
) ~= "string" then return FAIL(BADARG
, "user") end
1224 if not engineID
then
1225 local t
= session
:details()
1226 if t
.contextEngineIDLen
== 0 then
1227 -- we need an engineID and don't have one: probe with empty get-request
1228 local vb
, err
= session
:get(nil)
1229 if not vb
then return FAIL(BADENGPROBE
) end
1231 t
= session
:details()
1232 engineID
= t
.contextEngineID
1235 -- Prepare and execute the request
1238 if type(clonefrom
) ~= "string" then
1239 return FAIL(BADARG
, "clonefrom")
1242 -- oid is the new user
1243 local vb
= newvar(string.format("%s.%d.%s.%d.%s",
1245 string.len(engineID
), key2oid(engineID
),
1246 string.len(user
), key2oid(user
)),
1247 -- value is the row status
1248 rowStatus
.createAndGo
)
1249 table.insert(vl
, vb
)
1250 -- oid is the new user
1251 vb
= newvar(string.format("%s.%d.%s.%d.%s",
1252 usmOid
.userCloneFrom
,
1253 string.len(engineID
), key2oid(engineID
),
1254 string.len(user
), key2oid(user
)),
1255 -- value is the entry of clonefrom user
1256 string.format("%s.%d.%s.%d.%s",
1257 usmOid
.userSecurityName
,
1258 string.len(engineID
), key2oid(engineID
),
1259 string.len(clonefrom
), key2oid(clonefrom
)))
1260 table.insert(vl
, vb
)
1262 local vl
, err
, errindex
= session
:set(vl
)
1265 return FAIL(err
, "index " .. tostring(errindex
))
1274 local vb
= newvar(string.format("%s.%d.%s.%d.%s",
1276 string.len(engineID
), key2oid(engineID
),
1277 string.len(user
), key2oid(user
)),
1278 rowStatus
.createAndWait
)
1279 vb
, err
= session
:set(vb
)
1284 ------------------------------------------------------------------------------
1285 -- Active a created user and clone authentication from another
1287 -- @param session table - Session for performing the operation.
1288 -- @param user string - Name of user to create.
1289 -- @param clonefrom string - Name of user to clone.
1290 -- @return Varlist or nil + errormessage
1291 ------------------------------------------------------------------------------
1292 function clonefromuser(session
, user
, clonefrom
, engineID
)
1296 if type(clonefrom
) ~= "string" then return FAIL(BADARG
, "clonefrom") end
1297 if type(user
) ~= "string" then return FAIL(BADARG
, "user") end
1300 if not engineID
then
1301 local t
= session
:details()
1302 if t
.contextEngineIDLen
== 0 then
1303 -- we need an engineID and don't have one: probe with empty get-request
1304 local vb
, err
= session
:get(nil)
1305 if not vb
then return FAIL(BADENGPROBE
) end
1307 t
= session
:details()
1308 engineID
= t
.contextEngineID
1312 -- Set user row active
1313 local vb
= newvar(string.format("%s.%d.%s.%d.%s",
1315 string.len(engineID
), key2oid(engineID
),
1316 string.len(user
), key2oid(user
)),
1318 table.insert(vl
, vb
)
1320 -- oid is the new user
1321 vb
= newvar(string.format("%s.%d.%s.%d.%s",
1322 usmOid
.userCloneFrom
,
1323 string.len(engineID
), key2oid(engineID
),
1324 string.len(user
), key2oid(user
)),
1325 -- value is the entry of clonefrom user
1326 string.format("%s.%d.%s.%d.%s",
1327 usmOid
.userSecurityName
,
1328 string.len(engineID
), key2oid(engineID
),
1329 string.len(clonefrom
), key2oid(clonefrom
)))
1330 table.insert(vl
, vb
)
1333 local vl
, err
, errindex
= session
:set(vl
)
1336 return FAIL(err
,"index " .. tostring(errindex
))
1345 ------------------------------------------------------------------------------
1347 -- @param session table - Session for performing the operation.
1348 -- @param user string - Name of user to delete.
1349 -- @return varbind or nil + errormessage
1350 ------------------------------------------------------------------------------
1351 function deleteuser(session
, user
, engineID
)
1354 if type(user
) ~= "string" then return FAIL(BADARG
, "user") end
1357 if not engineID
then
1358 local t
= session
:details()
1359 if t
.contextEngineIDLen
== 0 then
1360 -- we need an engineID and don't have one: probe with empty get-request
1361 local vb
, err
= session
:get(nil)
1362 if not vb
then return FAIL(BADENGPROBE
) end
1364 t
= session
:details()
1365 engineID
= t
.contextEngineID
1369 local vb
= newvar(string.format("%s.%d.%s.%d.%s",
1371 string.len(engineID
), key2oid(engineID
),
1372 string.len(user
), key2oid(user
)),
1374 vb
, err
= session
:set(vb
)
1378 ------------------------------------------------------------------------------
1379 -- Create security name to group mapping.
1380 -- @param session table - Valid session.
1381 -- @param secmodel string - Security model 'SNMPv1', 'SNMPv2', 'USM'
1382 -- @param secname string - Security name.
1383 -- @param groupname string - Group name.
1384 -- @return varlist or nil + erromessage on failure
1385 ------------------------------------------------------------------------------
1386 function createsectogroup(session
, secmodel
, secname
, groupname
)
1388 if type(secmodel
) ~= "string" then return FAIL(BADARG
, "secmodel") end
1389 secmodel
= secmodels
[string.upper(secmodel
)]
1390 if type(secname
) ~= "string" then return FAIL(BADARG
, "secname") end
1391 if type(groupname
) ~= "string" then return FAIL(BADARG
, "groupname") end
1394 newvar(vacmOid
.sec2GroupStatus
..instance(secmodel
, secname
),
1395 rowStatus
.createAndGo
) ..
1396 newvar(vacmOid
.groupName
..instance(secmodel
, secname
),
1399 local vl
, err
, errindex
= session
:set(vl
)
1400 return retvarlist(vl
, err
, errindex
)
1404 ------------------------------------------------------------------------------
1405 -- Delete security name to group mapping.
1406 -- @param session table - Valid session.
1407 -- @param secmodel string - Security model 'SNMPv1', 'SNMPv2', 'USM'
1408 -- @param secname string - Security name.
1409 -- @return varlist or nil + erromessage on failure
1410 ------------------------------------------------------------------------------
1411 function deletesectogroup(session
, secmodel
, secname
)
1414 if type(secmodel
) ~= "string" then FAIL(BADARG
, "secmodel") end
1415 secmodel
= secmodels
[string.upper(secmodel
)]
1417 if type(secname
) ~= "string" then return FAIL(BADARG
, "secname") end
1418 local vb
= newvar(vacmOid
.sec2GroupStatus
..instance(secmodel
, secname
),
1422 vb
, err
= session
:set(vb
)
1426 ------------------------------------------------------------------------------
1427 -- Create a view for a subtree
1428 -- @param session table - Valid session.
1429 -- @param viewname string - Name for the created view.
1430 -- @param subtree oid - OID of view's subtree.
1431 -- @param mask string - Bitmask.
1432 -- @param flag string - "exc[lude]" or "inc[lude]" (default).
1433 -- @return varlist or nil + erromessage on failure
1434 ------------------------------------------------------------------------------
1435 function createview(session
, viewname
, subtree
, mask
, flag
)
1437 if type(viewname
) ~= "string" then return
1438 nil, errtb
[BADARG
].." (viewname)"
1440 if not isoid(subtree
) then return FAIL(BADARG
, "subtree") end
1441 if type(mask
) ~= "string" then return FAIL(BADARG
, "mask") end
1443 string.gsub(mask
, "([0-9A-Fa-f])([0-9A-Fa-f]*)",
1445 if d2
== "" then d2
= "0" end
1446 if string.len(d2
) ~= 1 then
1447 return nil, errtb
[BADARG
] .. " (mask)" end
1448 viewmask
= viewmask
.. string.char(tonumber(d1
,16)*16+tonumber(d2
,16))
1450 if not flag
then flag
= "include" end
1451 flag
= string.lower(flag
)
1452 if string.sub(flag
, 1,3) == "inc" then
1454 elseif string.sub(flag
, 1, 3) == "exc" then
1458 newvar(vacmOid
.viewTreeFamilyStatus
.. instance(viewname
, subtree
),
1459 rowStatus
.createAndGo
) ..
1460 newvar(vacmOid
.viewTreeFamilyMask
.. instance(viewname
, subtree
),
1461 key2octet(viewmask
)) ..
1462 newvar(vacmOid
.viewTreeFamilyType
.. instance(viewname
, subtree
),
1466 local vl
, err
, errindex
= session
:set(vl
)
1467 return retvarlist(vl
, err
, errindex
)
1470 ------------------------------------------------------------
1472 -- @param session table - Valid session.
1473 -- @param viewname string - Name for the created view.
1474 -- @param subtree oid - OID of view's subtree.
1475 -- @return varbind or nil + erromessage on failure
1476 ------------------------------------------------------------
1477 function deleteview(session
, viewname
, subtree
)
1479 if type(viewname
) ~= "string" then return FAIL(BADARG
, "viewname") end
1480 if not isoid(subtree
) then return FAIL(BADARG
, "subtree") end
1481 local vb
= newvar(vacmOid
.viewTreeFamilyStatus
.. instance(viewname
, subtree
),
1484 local vb
, err
= session
:set(vb
)
1488 ------------------------------------------------------------------------------
1489 -- Create Access Entry.
1490 -- @param session table - Valid session.
1491 -- @param group string - Group name.
1492 -- @param secmodel string - Security model 'SNMPv1', 'SNMPv2', 'USM'
1493 -- @param seclevel string - Security level 'authNoPriv' etc.
1494 -- @param match string - View ma
1495 -- @param secname string - Security name.
1496 -- @return varlist or nil + erromessage on failure
1497 ------------------------------------------------------------------------------
1498 function createaccess(session
, group
, secmodel
, seclevel
, match
,
1499 readview
, writeview
, notifyview
, context
)
1500 if type(secmodel
) ~= "string" then return FAIL(BADARG
, "secmodel") end
1501 secmodel
= secmodels
[string.upper(secmodel
)]
1502 if type(seclevel
) ~= "string" then return FAIL(BADARG
, "secname") end
1503 if not seclevels
[seclevel
] then return FAIL(BADARG
, "seclevel") end
1504 seclevel
= seclevels
[seclevel
]
1505 if type(match
) ~= "string" then return FAIL(BADARG
, "match") end
1507 if match
== "exact" then
1509 elseif match
== "prefix" then
1512 if not context
then context
= "" end
1513 local inst
= instance(group
, context
, secmodel
, seclevel
)
1515 newvar(vacmOid
.accessStatus
.. inst
, rowStatus
.createAndGo
) ..
1516 newvar(vacmOid
.accessContextMatch
.. inst
, nmatch
) ..
1517 newvar(vacmOid
.accessReadViewName
.. inst
, key2octet(readview
)) ..
1518 newvar(vacmOid
.accessWriteViewName
.. inst
, key2octet(writeview
)) ..
1519 newvar(vacmOid
.accessNotifyViewName
.. inst
, key2octet(notifyview
))
1522 local vl
, err
, errindex
= session
:set(vl
)
1523 return retvarlist(vl
, err
, errindex
)
1526 ------------------------------------------------------------------------------
1527 -- Delete security name to group mapping.
1528 -- @param session table - Valid session.
1529 -- @param secmodel string - Security model 'SNMPv1', 'SNMPv2', 'USM'
1530 -- @param secname string - Security name.
1531 -- @return varlist or nil + erromessage on failure
1532 ------------------------------------------------------------------------------
1533 function deleteaccess(session
, group
, secmodel
, seclevel
, context
)
1534 if type(secmodel
) ~= "string" then return FAIL(BADARG
, "secmodel") end
1535 secmodel
= secmodels
[string.upper(secmodel
)]
1536 if type(seclevel
) ~= "string" or not seclevels
[seclevel
] then
1537 return FAIL(BADARG
, "seclevel")
1539 seclevel
= seclevels
[seclevel
]
1541 if not context
then context
= "" end
1543 local inst
= instance(group
, context
, secmodel
, seclevel
)
1544 local vb
= newvar(vacmOid
.accessStatus
.. inst
, rowStatus
.destroy
)
1547 local vb
, err
= session
:set(vb
)
1551 ------------------------------------------------------------------------------
1552 -- Clones a valid session.
1553 -- Note: We disable session cloning because it leads to mangling of NET-SNMPs
1554 -- user list and hence doesn't work reliable enough. (NET-SNMP 5.7)
1555 -- @param parent table - Parent session.
1556 -- @param config table - Configuration (overrides parent's configuration)
1557 -- @return New session if o.k. Nil + error message otherwise.
1558 ------------------------------------------------------------------------------
1559 function __clone(parent
, config
)
1560 local new
= {parent
=parent
}
1561 config
= config
or {}
1563 if config
.version
then
1564 if config
.version
~= parent
.version
then return FAIL(BADVERSION
) end
1566 for k
, v
in pairs(parent
) do
1567 if parent
.version
~= SNMPv3
then
1568 if (k
~= "inform") then
1572 if config
.password
then
1573 if (k
~= "authPassphrase") and (k
~= "privPathphrase") then
1581 for k
, v
in pairs(config
or {}) do
1587 ------------------------------------------------------------------------------
1588 -- Table with session properties accessible using session.NAME using
1589 -- __index metamethod. Used to retrieve C internals provided by
1590 -- snmp.details() function.
1591 ------------------------------------------------------------------------------
1592 local sessionproperties
= {
1593 contextEngineID
= function(self
) return details(self
).contextEngineID
end,
1594 contextEngineIDLen
= function(self
) return details(self
).contextEngineIDLen
end,
1595 securityEngineID
= function(self
) return details(self
).securityEngineID
end,
1596 securityEngineIDLen
= function(self
) return details(self
).securityEngineIDLen
end,
1597 engineBoots
= function(self
) return details(self
).engineBoots
end,
1598 engineTime
= function(self
) return details(self
).engineTime
end,
1599 isAuthoritative
= function(self
) return details(self
).isAuthoritative
end
1602 ---------------------------------------------------------------------------
1603 -- Create a new SNMP session.
1604 -- @param session table - Base parameters.
1605 -- @return Active session.
1606 ---------------------------------------------------------------------------
1607 function open (session
)
1613 -- Be sure to have the correct parameter type
1614 if type(session
)~="table" then
1615 return FAIL(BADSESSION
)
1618 if not session
.name
then
1619 session
.name
= "nobody"
1622 -- SNMP Version: v1, v2c (default) or v3
1623 if not session
.version
then
1624 session
.version
=tonumber(config
.defVersion
) or SNMPv2C
1626 if (session
.version
~= SNMPv1
and
1627 session
.version
~= SNMPv2C
and
1628 session
.version
~= SNMPv3
) then
1629 return FAIL(BADVERSION
)
1632 -- Printing variables
1633 if session
.sprintvar
then
1634 if type(session
.sprintvar
) ~= "function" then
1635 return FAIL(BADPRINTVAR
)
1638 session
.sprintvar
= sprint_variable
1642 if session
.sprintval
then
1643 if type(session
.sprintval
) ~= "function" then
1644 return FAIL(BADPRINTVAL
)
1647 session
.sprintval
= sprint_value
1650 -- Version 2: community: any or public (default)
1651 if session
.version
== SNMPv2c
then
1652 if not session
.community
then
1653 session
.community
= config
.defCommunity
or "public"
1655 if type(session
.community
)~="string" then
1656 return FAIL(BADCOMMUNITY
)
1661 if session
.version
== SNMPv3
then
1664 if not session
.user
then
1665 session
.user
= config
.defSecurityName
1667 if not session
.user
then
1668 return FAIL(BADUSER
)
1671 -- security level: authPriv, authNoPriv (default) or noAuthNoPriv
1672 if not session
.securityLevel
then
1673 session
.securityLevel
= config
.defSecurityLevel
or "authNoPriv"
1675 if not seclevels
[session
.securityLevel
] then
1676 return FAIL(BADSECLEVEL
)
1678 session
._securityLevel
= seclevels
[session
.securityLevel
]
1681 -- authentication protocol: MD5 (default) or SHA
1682 if not session
.authType
then
1683 session
.authType
= config
.defAuthType
or "MD5"
1686 -- authentication passphrase: any
1687 if not session
.password
and not session
.authPassphrase
then
1688 session
.authPassphrase
= config
.defPassphrase
or config
.defAuthPassphrase
1690 session
.authPassphrase
= session
.authPassphrase
or session
.password
1692 if not session
.authPassphrase
then
1693 return FAIL(BADPASSPHRASE
)
1696 -- encryption protocol: DES (default) or AES
1697 if not session
.privType
then
1698 session
.privpType
= config
.defPrivType
or "DES"
1701 -- privacy passphrase: any
1702 if not session
.password
and not session
.privPassphrase
then
1703 session
.privPassphrase
= config
.defPassphrase
or config
.defPrivPassphrase
1705 session
.privPassphrase
= session
.privPassphrase
or session
.password
1707 if not session
.privPassphrase
then
1708 return FAIL(BADPRIVPASSPHRASE
)
1712 if not session
.context
then
1713 session
.context
= ""
1716 -- authentication engine ID:
1717 if not session
.engineID
then
1718 session
.engineID
= nil
1721 -- context engine ID:
1722 if not session
.contextID
then
1723 session
.contextID
= session
.engineID
1726 -- engine boots: not supported yet
1727 if not session
.engineBoots
then
1728 session
.engboots
= nil
1730 return FAIL(BADENGBOOTS
)
1733 -- engine time: not supported yet
1734 if not session
.engineTime
then
1735 session
.engtime
= nil
1737 return FAIL(BADENGTIME
)
1741 -- timeout: any or 1s (default)
1742 if not session
.timeout
then
1745 session
.timeout
= tonumber(session
.timeout
)
1746 if not session
.timeout
then
1747 return FAIL(BADTIME
)
1748 elseif session
.timeout
< 0 then
1749 return FAIL(BADTIME
)
1753 -- retries: any or 5 (default)
1754 if not session
.retries
then
1757 session
.retries
= tonumber(session
.retries
)
1758 if not session
.retries
then
1759 return FAIL(BADRETRIES
)
1760 elseif session
.retries
< 0 then
1761 return FAIL(BADRETRIES
)
1765 -- agent: any or 0.0.0.0 (default)
1766 if not session
.peer
then
1767 session
.peer
= "0.0.0.0"
1768 elseif type(session
.peer
)~="string" then
1769 return FAIL(BADPEER
)
1772 -- port: any or 161 (default)
1773 if not session
.port
then
1774 session
.port
= config
.defaultPort
or 161
1776 session
.port
= tonumber(session
.port
)
1777 if not session
.port
then
1778 return FAIL(BADPORT
)
1779 elseif session
.port
< 0 then
1780 return FAIL(BADPORT
)
1784 -- default callback:
1785 if session
.callback
then
1786 if type(session
.callback
) ~= "function" then
1787 return FAIL(BADCALLBACK
)
1792 if session
.trap
then
1793 if type(session
.trap
) ~= "function" then
1794 return FAIL(BADTRAP
)
1796 session
.usertrap
= session
.trap
1797 session
.trap
= __trap
1801 if session
.inform
then
1802 if session
.version
== SNMPv1
then
1803 return FAIL(INVINFO
)
1805 if type(session
.inform
) ~= "function" then
1806 return FAIL(BADINFO
)
1811 if session
.includeroot
then
1812 if session
.version
== SNMPv1
then
1813 return FAIL(INVINFO
)
1815 if type(session
.includeroot
) ~= "boolean" then
1816 return FAIL(BADINCL
)
1819 session
.includeroot
= false
1823 -- This opens the net-snmp session
1825 local intsess
, ip_err
= _open(session
)
1826 if not intsess
then return nil, ip_err
end
1829 session
.verid
= "LuaSNMP " .. snmp
.version
1830 session
.internal
= intsess
1831 session
.peer_ip
= ip_err
1832 session
.getversion
= function(self
)
1834 return FAIL(BADSESSION
)
1836 if self
.version
== SNMPv1
then
1838 elseif self
.version
== SNMPv2c
then
1840 elseif self
.version
== SNMPv3
then
1843 return FAIL(BADSESSION
)
1847 -- map snmp methods to the session
1850 session
.getnext
= getnext
1851 session
.getbulk
= getbulk
1852 session
.asynch_get
= asynch_get
1853 session
.asynch_getnext
= asynch_getnext
1854 session
.asynch_getbulk
= asynch_getbulk
1855 session
.close
= function(self
)
1856 -- We need to remove the running user from library's userList.
1857 -- Otherwise a new session with new passowrd to the same machine (engineID) fails.
1858 if session
.version
== SNMPv3
then
1859 self
:removeuser(rawget(self
,"user"))
1861 return close(session
)
1864 session
.asynch_set
= asynch_set
1865 session
.inform
= inform
1866 session
.asynch_inform
= asynch_inform
1868 session
.newvar
= function(session
, name
, value
, type)
1869 return newvar(name
, value
, type, session
)
1871 -- session.clone = clone
1872 session
.newpassword
= newpassword
1873 session
.createuser
= createuser
1874 session
.deleteuser
= deleteuser
1875 session
.clonefromuser
= clonefromuser
1876 session
.details
= details
1877 session
.createsectogroup
= createsectogroup
1878 session
.deletesectogroup
= deletesectogroup
1879 session
.createview
= createview
1880 session
.deleteview
= deleteview
1881 session
.createaccess
= createaccess
1882 session
.deleteaccess
= deleteaccess
1883 session
.removeuser
= removeuser
1885 -- A cache with weak values for SNMP object type cacheing.
1888 setmetatable(session
.cache
, {__mode
="v"})
1889 setmetatable(session
, {
1891 -- Syntactic sugar: val = sess.OBJECT <=> val = sess:get(OBJECT)
1892 __index
= function(self
, key
)
1893 if sessionproperties
[key
] then
1894 return sessionproperties
[key
](self
)
1896 local name
= string.gsub(key
, "_",".")
1897 local rv
, err
= self
:walk(name
)
1900 -- No successor and single: return scalar
1903 -- No successor and multiple: return list of values
1905 for _
,v
in ipairs(rv
) do
1906 t
[mib
.name(v
.oid
)] = v
.value
1912 -- Syntactic sugar: sess.OBJECT = val <=> sess:set(OBJECT)
1913 __newindex
= function(self
, key
, value
)
1914 local name
= string.gsub(key
, "_",".")
1915 -- Value is a table. Set all values - recursive.
1916 if type(value
) == "table" then
1917 for k
,v
in pairs(v
) do
1921 return try(self
:set
{oid
=name
, value
=value
})
1924 __newindex2
= function(self
, key
, value
)
1925 local name
= string.gsub(key
, "_",".")
1926 -- Value is a table. Set all values - recursive.
1927 if type(value
) == "table" then
1928 for k
,v
in pairs(v
) do
1932 -- Look for an entry in the varbinding cache
1933 local entry
= self
.cache
[name
]
1935 -- found one: just enter the value
1937 return try(self
:set(entry
))
1939 -- no entry found: construct a new varbinding and
1940 -- put it into the cache.
1941 local oid
= mib
.oid(name
)
1942 local entry
= {oid
=oid
, type=mib
.type(oid
), value
=value
}
1943 self
.cache
[name
] = entry
1944 return try(self
:set(entry
))
1949 -- Return the session handle
1954 local _assert
= _G
.assert
1955 ---------------------------------------------------------------------------
1956 -- Check result of a function.
1957 -- The function performs an extended check on both exp == true and a nil
1958 -- error message instead of just check the expression exp as assert does.
1959 -- @param exp boolean - Expression to check.
1960 -- @param err string - Error message to evaluate.
1961 -- @return exp if (exp == true) and (err == nil), exit otherwise
1962 ---------------------------------------------------------------------------
1963 function check(exp, err
, ...)
1964 if exp ~= nil and not err
then
1967 _assert(exp, err
or "unknown")