1 module snmp.session; 2 3 import c.net_snmp; 4 import snmp.types; 5 import snmp.oid; 6 import snmp.pdu : SNMPResponse; 7 8 /// Lightweight SNMP session wrapper (RAII, non-copyable). 9 struct SNMPSession 10 { 11 netsnmp_session* handle; 12 13 @disable this(this); 14 15 static SNMPSession open( 16 scope const(char)* peername, 17 scope const(char)* community, 18 SNMPVersion ver = SNMPVersion.v2c) @trusted @nogc nothrow 19 { 20 SNMPSession s; 21 22 if (!peername || !community) 23 return s; 24 25 netsnmp_session sess; 26 snmp_sess_init(&sess); 27 28 // `version` is a D keyword — access via __traits 29 __traits(getMember, sess, "version") = cast(long) ver; 30 sess.peername = cast(char*) peername; 31 sess.community = cast(ubyte*) community; 32 33 import core.stdc.string : strlen; 34 35 sess.community_len = strlen(community); 36 37 s.handle = snmp_open(&sess); 38 return s; 39 } 40 41 static SNMPSession open( 42 string peername, 43 string community, 44 SNMPVersion ver = SNMPVersion.v2c) 45 { 46 import std.string : toStringz; 47 48 return open(peername.toStringz, community.toStringz, ver); 49 } 50 51 ~this() @trusted @nogc nothrow { close(); } 52 53 void close() @trusted @nogc nothrow 54 { 55 if (handle) 56 { 57 snmp_close(handle); 58 handle = null; 59 } 60 } 61 62 bool isOpen() const @nogc nothrow @safe 63 { 64 return handle !is null; 65 } 66 67 SNMPResponse get(scope const OID o) @trusted @nogc nothrow 68 { 69 if (!isOpen || !o.isValid) 70 return SNMPResponse(null, STAT_ERROR); 71 72 auto pdu = snmp_pdu_create(cast(int) PDUType.get); 73 snmp_add_null_var(pdu, o.data.ptr, o.length); 74 75 netsnmp_pdu* resp; 76 int stat = snmp_synch_response(handle, pdu, &resp); 77 return SNMPResponse(resp, stat); 78 } 79 80 SNMPResponse getNext(scope const OID o) @trusted @nogc nothrow 81 { 82 if (!isOpen || !o.isValid) 83 return SNMPResponse(null, STAT_ERROR); 84 85 auto pdu = snmp_pdu_create(cast(int) PDUType.getNext); 86 snmp_add_null_var(pdu, o.data.ptr, o.length); 87 88 netsnmp_pdu* resp; 89 int stat = snmp_synch_response(handle, pdu, &resp); 90 return SNMPResponse(resp, stat); 91 } 92 93 /// SNMPv2c/v3 only. non_repeaters/max_repetitions map to errstat/errindex. 94 SNMPResponse getBulk(scope const OID o, 95 int nonRepeaters = 0, 96 int maxRepetitions = 10) @trusted @nogc nothrow 97 { 98 if (!isOpen || !o.isValid) 99 return SNMPResponse(null, STAT_ERROR); 100 101 auto pdu = snmp_pdu_create(cast(int) PDUType.getBulk); 102 pdu.errstat = nonRepeaters; 103 pdu.errindex = maxRepetitions; 104 snmp_add_null_var(pdu, o.data.ptr, o.length); 105 106 netsnmp_pdu* resp; 107 int stat = snmp_synch_response(handle, pdu, &resp); 108 return SNMPResponse(resp, stat); 109 } 110 } 111 112 unittest 113 { 114 init_snmp("snmp-d-test"); 115 116 auto bad = SNMPSession.open(cast(const(char)*) null, "public", SNMPVersion.v2c); 117 assert(!bad.isOpen); 118 119 bad.close(); 120 bad.close(); 121 assert(!bad.isOpen); 122 }