1 // example3 — AgentX subagent
2 //
3 // Connects to a running snmpd master agent and registers two read-only scalars:
4 //
5 //   1.3.6.1.4.1.99999.1.0  Counter32  — number of GET queries received
6 //   1.3.6.1.4.1.99999.2.0  OctetStr   — hostname of the machine
7 //
8 // Requirements:
9 //   snmpd must have AgentX enabled. Add to /etc/snmp/snmpd.conf:
10 //     master agentx
11 //   Then restart: sudo systemctl restart snmpd
12 //
13 // Run:
14 //   ./build/examples_subagent
15 //
16 // Test (in another terminal):
17 //   snmpget -v2c -c public localhost 1.3.6.1.4.1.99999.1.0
18 //   snmpget -v2c -c public localhost 1.3.6.1.4.1.99999.2.0
19 module example3;
20 
21 import snmp;
22 import std.stdio : writefln, stderr;
23 import core.sys.posix.signal : signal, SIGINT, SIGTERM;
24 import core.stdc.string : strlen;
25 
26 private alias size_t = object.size_t;
27 
28 private __gshared bool _running = true;
29 private __gshared uint _queryCount = 0;
30 
31 extern (C) private void onSignal(int) @trusted nothrow @nogc
32 {
33     _running = false;
34 }
35 
36 extern (C) private int counterHandler(
37     netsnmp_mib_handler*,
38     netsnmp_handler_registration*,
39     netsnmp_agent_request_info* reqinfo,
40     netsnmp_request_info* requests) @trusted @nogc nothrow
41 {
42     auto req = ScalarRequest(reqinfo, requests);
43     if (req.isGet)
44     {
45         ++_queryCount;
46         req.setCounter(_queryCount);
47     }
48     return SNMP_ERR_NOERROR;
49 }
50 
51 extern (C) private int hostnameHandler(
52     netsnmp_mib_handler*,
53     netsnmp_handler_registration*,
54     netsnmp_agent_request_info* reqinfo,
55     netsnmp_request_info* requests) @trusted @nogc nothrow
56 {
57     import core.sys.posix.unistd : gethostname;
58 
59     __gshared char[256] buf;
60     auto req = ScalarRequest(reqinfo, requests);
61     if (req.isGet)
62     {
63         gethostname(buf.ptr, buf.sizeof - 1);
64         req.setOctetStr(cast(ubyte[]) buf[0 .. strlen(buf.ptr)]);
65     }
66     return SNMP_ERR_NOERROR;
67 }
68 
69 void main() @trusted
70 {
71     signal(SIGINT, &onSignal);
72     signal(SIGTERM, &onSignal);
73 
74     // true = AgentX subagent mode
75     auto agent = SNMPAgent.create("example3", true);
76     if (!agent.isReady)
77     {
78         stderr.writefln("Agent init failed — is snmpd running with 'master agentx'?");
79         return;
80     }
81 
82     agent.registerScalar("demoCounter",
83         cast(Netsnmp_Node_Handler*)&counterHandler,
84         OID.fromSlice([1, 3, 6, 1, 4, 1, 99999, 1, 0]));
85 
86     agent.registerScalar("demoHostname",
87         cast(Netsnmp_Node_Handler*)&hostnameHandler,
88         OID.fromSlice([1, 3, 6, 1, 4, 1, 99999, 2, 0]));
89 
90     writefln("Subagent running (Ctrl+C to stop).");
91     writefln("  snmpget -v2c -c public localhost 1.3.6.1.4.1.99999.1.0");
92     writefln("  snmpget -v2c -c public localhost 1.3.6.1.4.1.99999.2.0");
93 
94     while (_running)
95         agent.process();
96 }