Source file netsnmp_monad.ml
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
open Netsnmp_raw_monad
let option_default ~default v = match v with Some v -> v | None -> default
module type IO = Io_intf.S
module Netsnmp(IO : IO) : Netsnmp_intf.S with module IO := IO = struct
open IO
module ASN1_value = ASN1_value
include Netsnmp_types
module Mib = Mib_monad.Mib(IO)
module Session = Session_monad.Session(IO)
module Pdu = Pdu_monad.Pdu(IO)
let list_iter ~f l =
let rec loop = function
| [] -> return ()
| hd::tl -> f hd >>= fun () -> loop tl
in
loop l
let list_fold ~init ~f l =
let rec loop a = function
| [] -> return a
| hd::tl -> f a hd >>= fun a -> loop a tl
in
loop init l
module Oid = struct
include Oid
(** Track the mibs that have been loaded *)
let loaded_mibs = ref []
let initialised = ref false
let check_init () =
match !initialised with
| true -> return ()
| false ->
Mib.netsnmp_init_mib ()
>>= fun () ->
initialised := true;
return ()
let oid_module =
let re = Re.(compile (rep1 (char ':'))) in
fun oidstr ->
match Re.split re oidstr with
| oidm::_::_ -> Some oidm
| _ -> None
;;
let of_string oidstr =
check_init ()
>>= fun () ->
match oid_module oidstr with
| Some oidm -> begin
if not (List.exists (String.equal oidm) !loaded_mibs) then begin
Mib.netsnmp_read_module oidm
>>= fun () ->
loaded_mibs := oidm::!loaded_mibs;
return ()
end
else
return ()
end
>>= fun () ->
Mib.get_node oidstr
| None ->
Mib.get_node oidstr
;;
let to_string oidstr = check_init () >>= fun () -> Mib.snprint_objid oidstr
end
module Connection = struct
type t = {
session : Netsnmp_raw.Session.t
; mutable closed : bool
}
let version_auth_to_version = function
| Snmp_version_auth.Version_1 _ -> Session.Snmp_version.Version_1
| Version_2c _ -> Version_2c
| Version_3 _ -> Version_3
let close sess =
begin
if not sess.closed then Session.snmp_sess_close sess.session
else return ()
end
>>= fun () ->
sess.closed <- true;
return ()
let connect (cinfo:Connection_info.t) =
Oid.check_init ()
>>= fun () ->
let version = version_auth_to_version cinfo.version_auth in
let retries = option_default ~default:3 cinfo.retries in
let timeout = option_default ~default:3_000_000 cinfo.timeout in
let peername = cinfo.peername in
let localname = option_default ~default:"" cinfo.localname in
let local_port = option_default ~default:0 cinfo.local_port in
let (, securityName, securityAuthProto, securityAuthPassword) =
match cinfo.version_auth with
| Snmp_version_auth.Version_1 auth | Version_2c auth ->
(auth.community, "", Session.Snmp_sec_auth_proto.Ignore, "")
| Version_3 auth ->
("", auth.securityName, auth.securityAuthProto, auth.securityAuthPassword)
in
Session.snmp_sess_init ()
>>= fun netsnmp_session ->
Session.snmp_sess_open
~netsnmp_session ~version ~retries ~timeout ~peername ~localname ~local_port
~community ~securityName ~securityAuthProto ~securityAuthPassword ()
>>= fun session ->
let t = {
session
; closed = false
}
in
let () = IO.gc_finalise (fun t -> close t) t in
return t
let with_connection cinfo ~f =
connect cinfo
>>= fun sess ->
match f sess with
| exception e -> close sess >>= fun () -> raise e
| _ as res -> close sess >>= fun () -> return res
end
let add_mibdir p =
Oid.check_init ()
>>= fun () ->
Mib.add_mibdir p
>>= function
| i when i < 0 -> raise (Failure ("add_mibdir failed: " ^ p))
| _ -> return ()
;;
let add_mib_paths paths = list_iter ~f:add_mibdir paths
let check_sess (sess:Connection.t) =
match sess.closed with
| true -> raise (Failure "session has been closed")
| _ -> ()
;;
let get_s (sess:Connection.t) oids =
let () = check_sess sess in
let add_oid oid pdu = Oid.of_string oid >>= Pdu.snmp_add_null_var pdu in
Pdu.snmp_pdu_create Pdu.Pdu_type.Get
>>= fun pdu ->
list_fold ~init:pdu ~f:(fun pdu oid -> add_oid oid pdu) oids
>>= fun pdu ->
Session.snmp_sess_synch_response sess.session pdu
;;
let get (sess:Connection.t) oids =
let () = check_sess sess in
let add_oid oid pdu = Pdu.snmp_add_null_var pdu oid in
Pdu.snmp_pdu_create Pdu.Pdu_type.Get
>>= fun pdu ->
list_fold ~init:pdu ~f:(fun pdu oid -> add_oid oid pdu) oids
>>= fun pdu ->
Session.snmp_sess_synch_response sess.session pdu
;;
let get_next (sess:Connection.t) oid =
let () = check_sess sess in
Pdu.snmp_pdu_create Pdu.Pdu_type.Getnext
>>= fun pdu ->
Pdu.snmp_add_null_var pdu oid
>>= fun pdu ->
Session.snmp_sess_synch_response sess.session pdu
;;
module Raw = struct
module Oid = Oid
module Pdu = Pdu_monad.Pdu(IO)
module Mib = Mib_monad.Mib(IO)
module Session = Session_monad.Session(IO)
end
end