-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsnmp-agentx.lua
153 lines (134 loc) · 3.57 KB
/
snmp-agentx.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env lua
-- EBM SNMP Subagent - AgentX implementation
-- Copyright (C) 2023, coreMem Limited <[email protected]>
-- SPDX-License-Identifier: AGPL-3.0-only
local clock_gettime = require"posix".clock_gettime
local poll = require "posix.poll"
local time = require "posix.time"
local dir = arg[0]:match("^(.-/?)[^/]+.lua$")
local status, agentx = pcall(function () return require "agentx" end)
if not status then
agentx = assert(loadfile(dir .. "agentx.lua"))()
end
local status, ebm = pcall(function () return require "ebm" end)
if not status then
ebm = assert(loadfile(dir .. "ebm.lua"))()
end
if #arg < 2 then
io.stderr:write("Usage: " .. arg[0] .. " IFACE MACADDR\n")
os.exit(1)
end
-- see issue #2
local IFINDEX = os.getenv("IFINDEX")
if not IFINDEX then
math.randomseed(os.time())
IFINDEX = 10000 + math.random(10000)
end
-- timer wheel with millisecond resolution
local Wheel = { mt = {} }
function Wheel.new ()
local w = { _k = {}, _v = {} }
setmetatable(w, Wheel.mt)
rawset(w, '_now', function ()
local n = {clock_gettime(time.CLOCK_MONOTONIC)}
return (n[1] * 1000) + math.floor((n[2] / 1000000))
end)
rawset(w, 'next', function ()
return (#w._k > 0) and math.max(0, w._k[1] - w._now()) or nil
end)
rawset(w, 'fire', function ()
local t = w._now()
for i=#w._k,1,-1 do
if w._k[i] > t then
break
end
if type(w._v[i]) == "function" then
pcall(function() return w._v[i]() end)
elseif type(w._v[i]) == "thread" then
coroutine.resume(w._v[i])
end
table.remove(w._k, i)
table.remove(w._v, i)
end
end)
return w
end
function Wheel.mt.__newindex (w, k, v)
-- if less than a year, assume relative to now
if k < 31536000000 then
k = k + w._now()
end
if #w._k == 0 then
table.insert(w._k, k)
table.insert(w._v, v)
else
for wi, wv in ipairs(w._k) do
if k <= kk then
table.insert(w._k, i, k)
table.insert(w._v, i, v)
break
end
end
end
end
local wheel = Wheel.new()
local ebm_session = ebm:session({iface=arg[1], addr=arg[2]})
if not ebm_session then
error(err)
end
local ax_cb = function (session, request)
local response
io.stderr:write("nyi, " .. tostring(request._hdr.type) .. "\n")
return response
end
local ax_session, err = agentx:session({ name="EBM: " .. arg[2] .. "%" .. arg[1], cb=ax_cb })
if not ax_session then
error(err)
end
local ifTable = {1,3,6,1,2,1,2,2}
local ifTable_ifIndex = {unpack(ifTable)}
table.insert(ifTable_ifIndex, 1) -- ifEntry
table.insert(ifTable_ifIndex, 1) -- ifIndex
local ifIndex
-- local ifIndex, err = ax_session:index_allocate({ ["type"]=agentx.VTYPE.Integer, name=ifTable_ifIndex, flags=agentx.FLAGS.NEW_INDEX })
local ifIndex, err = ax_session:index_allocate({ ["type"]=agentx.VTYPE.Integer, name=ifTable_ifIndex, data = IFINDEX })
if not ifIndex then
error(err)
end
local status, err = assert(loadfile(dir .. "snmp-agentx-mib.lua"))(agentx, ax_session, ifIndex, ebm, ebm_session, wheel)
if not status then
error(err)
end
local fds = {
[ax_session.fd] = { events = { IN = true } },
[ebm_session.fd] = { events = { IN = true } }
}
while true do
local status, ret = pcall(function() return poll.poll(fds, wheel.next() or -1) end)
if not status then
error(ret)
end
if ret == 0 then
wheel.fire()
end
for k, v in pairs(fds) do
if v.revents then
local err
if v.revents.IN then
if k == ax_session.fd then
status, err = ax_session:process()
else
status, err = ebm_session:process()
end
if not status then
error(err)
end
v.revents.IN = false
elseif v.revents.HUP then
error("nyi")
end
end
end
end
ax_session:close()
ebm_session:close()