1
%% ``The contents of this file are subject to the Erlang Public License,
2
%% Version 1.1, (the "License"); you may not use this file except in
3
%% compliance with the License. You should have received a copy of the
4
%% Erlang Public License along with this software. If not, it can be
5
%% retrieved via the world wide web at http://www.erlang.org/.
7
%% Software distributed under the License is distributed on an "AS IS"
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
%% the License for the specific language governing rights and limitations
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
%% AB. All Rights Reserved.''
18
%%----------------------------------------------------------------------
19
%% This module examplifies how to write test suites for your SNMP agent.
20
%%----------------------------------------------------------------------
22
-module(snmp_ex2_manager).
24
-behaviour(gen_server).
25
-behaviour(snmpm_user).
27
-export([start_link/0, start_link/1, stop/0,
29
sync_get/2, sync_get/3,
30
sync_get_next/2, sync_get_next/3,
31
sync_get_bulk/4, sync_get_bulk/5,
32
sync_set/2, sync_set/3,
37
%% Manager callback API:
38
-export([handle_error/3,
45
%% gen_server callbacks
46
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
47
code_change/3, terminate/2]).
49
-include_lib("snmp/include/snmp_types.hrl").
52
-define(SERVER, ?MODULE).
53
-define(USER, ?MODULE).
54
-define(USER_MOD, ?MODULE).
56
-record(state, {parent}).
59
%%%-------------------------------------------------------------------
61
%%%-------------------------------------------------------------------
66
start_link(Opts) when is_list(Opts) ->
67
gen_server:start_link({local, ?SERVER}, ?MODULE, [self(), Opts], []).
73
%% --- Instruct manager to handle an agent ---
76
call({agent, Addr, Conf}).
78
agent(Addr, Port, Conf) ->
79
call({agent, Addr, Port, Conf}).
82
%% --- Misc utility functions ---
85
call({oid_to_name, Oid}).
88
%% --- Various SNMP operations ----
90
sync_get(Addr, Oids) ->
91
call({sync_get, Addr, Oids}).
93
sync_get(Addr, Port, Oids) ->
94
call({sync_get, Addr, Port, Oids}).
97
sync_get_next(Addr, Oids) ->
98
call({sync_get_next, Addr, Oids}).
100
sync_get_next(Addr, Port, Oids) ->
101
call({sync_get_next, Addr, Port, Oids}).
104
sync_get_bulk(Addr, NR, MR, Oids) ->
105
call({sync_get_bulk, Addr, NR, MR, Oids}).
107
sync_get_bulk(Addr, Port, NR, MR, Oids) ->
108
call({sync_get_bulk, Addr, Port, NR, MR, Oids}).
111
sync_set(Addr, VarsAndVals) ->
112
call({sync_set, Addr, VarsAndVals}).
114
sync_set(Addr, Port, VarsAndVals) ->
115
call({sync_set, Addr, Port, VarsAndVals}).
118
%%%-------------------------------------------------------------------
119
%%% Callback functions from gen_server
120
%%%-------------------------------------------------------------------
122
init([Parent, Opts]) ->
123
process_flag(trap_exit, true),
124
case (catch do_init(Opts)) of
126
{ok, State#state{parent = Parent}};
134
{Dir, MgrConf, MgrOpts} = parse_opts(Opts),
135
write_config(Dir, MgrConf),
136
start_manager(MgrOpts),
140
write_config(Dir, Conf) ->
141
case snmp_config:write_manager_config(Dir, "", Conf) of
145
error({failed_writing_config, Error})
148
start_manager(Opts) ->
149
case snmpm:start_link(Opts) of
153
error({failed_starting_manager, Error})
157
case snmpm:register_user(?USER, ?USER_MOD, self()) of
161
error({failed_register_user, Error})
165
Port = get_opt(port, Opts, 5000),
166
EngineId = get_opt(engine_id, Opts, "mgrEngine"),
167
MMS = get_opt(max_message_size, Opts, 484),
169
MgrConf = [{port, Port},
170
{engine_id, EngineId},
171
{max_message_size, MMS}],
174
Mibs = get_opt(mibs, Opts, []),
175
Vsns = get_opt(versions, Opts, [v1, v2, v3]),
176
{ok, Cwd} = file:get_cwd(),
177
Dir = get_opt(dir, Opts, Cwd),
178
MgrOpts = [{mibs, Mibs},
180
%% {server, [{verbosity, trace}]},
181
{config, [% {verbosity, trace},
182
{dir, Dir}, {db_dir, Dir}]}],
184
{Dir, MgrConf, MgrOpts}.
187
%%--------------------------------------------------------------------
188
%% Func: handle_call/3
189
%% Returns: {reply, Reply, State} |
190
%% {reply, Reply, State, Timeout} |
191
%% {noreply, State} |
192
%% {noreply, State, Timeout} |
193
%% {stop, Reason, Reply, State} | (terminate/2 is called)
194
%% {stop, Reason, State} (terminate/2 is called)
195
%%--------------------------------------------------------------------
197
handle_call({agent, Addr, Conf}, _From, S) ->
198
Reply = (catch snmpm:register_agent(?USER, Addr, Conf)),
201
handle_call({agent, Addr, Port, Conf}, _From, S) ->
202
Reply = (catch snmpm:register_agent(?USER, Addr, Port, Conf)),
205
handle_call({oid_to_name, Oid}, _From, S) ->
206
Reply = (catch snmpm:oid_to_name(Oid)),
209
handle_call({sync_get, Addr, Oids}, _From, S) ->
210
Reply = (catch snmpm:g(?USER, Addr, Oids)),
213
handle_call({sync_get, Addr, Port, Oids}, _From, S) ->
214
Reply = (catch snmpm:g(?USER, Addr, Port, Oids)),
217
handle_call({sync_get_next, Addr, Oids}, _From, S) ->
218
Reply = (catch snmpm:gn(?USER, Addr, Oids)),
221
handle_call({sync_get_next, Addr, Port, Oids}, _From, S) ->
222
Reply = (catch snmpm:gn(?USER, Addr, Port, Oids)),
225
handle_call({sync_get_bulk, Addr, NR, MR, Oids}, _From, S) ->
226
Reply = (catch snmpm:gb(?USER, Addr, NR, MR, Oids)),
229
handle_call({sync_get_bulk, Addr, Port, NR, MR, Oids}, _From, S) ->
230
Reply = (catch snmpm:gb(?USER, Addr, Port, NR, MR, Oids)),
233
handle_call({sync_set, Addr, VarsAndVals}, _From, S) ->
234
Reply = (catch snmpm:s(?USER, Addr, VarsAndVals)),
237
handle_call({sync_set, Addr, Port, VarsAndVals}, _From, S) ->
238
Reply = (catch snmpm:s(?USER, Addr, Port, VarsAndVals)),
241
handle_call(Req, From, State) ->
242
error_msg("received unknown request ~n~p~nFrom ~p", [Req, From]),
243
{reply, {error, {unknown_request, Req}}, State}.
246
%%--------------------------------------------------------------------
247
%% Func: handle_cast/2
248
%% Returns: {noreply, State} |
249
%% {noreply, State, Timeout} |
250
%% {stop, Reason, State} (terminate/2 is called)
251
%%--------------------------------------------------------------------
252
handle_cast(stop, S) ->
253
(catch snmpm:stop()),
256
handle_cast(Msg, State) ->
257
error_msg("received unknown message ~n~p", [Msg]),
261
%%--------------------------------------------------------------------
262
%% Func: handle_info/2
263
%% Returns: {noreply, State} |
264
%% {noreply, State, Timeout} |
265
%% {stop, Reason, State} (terminate/2 is called)
266
%%--------------------------------------------------------------------
267
handle_info({snmp_callback, Tag, Info}, State) ->
268
handle_snmp_callback(Tag, Info),
271
handle_info(Info, State) ->
272
error_msg("received unknown info: "
273
"~n Info: ~p", [Info]),
277
%%--------------------------------------------------------------------
279
%% Purpose: Shutdown the server
280
%% Returns: any (ignored by gen_server)
281
%%--------------------------------------------------------------------
282
terminate(_Reason, _State) ->
286
code_change({down, _Vsn}, State, _Extra) ->
290
code_change(_Vsn, State, _Extra) ->
294
%% ========================================================================
295
%% ========================================================================
297
handle_snmp_callback(handle_error, {ReqId, Reason}) ->
298
io:format("*** FAILURE ***"
301
"~n", [ReqId, Reason]),
303
handle_snmp_callback(handle_agent, {Addr, Port, SnmpInfo}) ->
304
{ES, EI, VBs} = SnmpInfo,
305
io:format("*** UNKNOWN AGENT ***"
309
"~n Error Status: ~w"
312
"~n", [Addr, Port, ES, EI, VBs]),
314
handle_snmp_callback(handle_pdu, {Addr, Port, ReqId, SnmpResponse}) ->
315
{ES, EI, VBs} = SnmpResponse,
316
io:format("*** Received PDU ***"
321
"~n Error Status: ~w"
324
"~n", [Addr, Port, ReqId, ES, EI, VBs]),
326
handle_snmp_callback(handle_trap, {Addr, Port, SnmpTrap}) ->
329
{Enteprise, Generic, Spec, Timestamp, Varbinds} ->
330
io_lib:format("~n Generic: ~w"
335
[Generic, Enteprise, Spec, Timestamp, Varbinds]);
336
{ErrorStatus, ErrorIndex, Varbinds} ->
337
io_lib:format("~n Error Status: ~w"
340
"~n", [ErrorStatus, ErrorIndex, Varbinds])
342
io:format("*** Received TRAP ***"
346
"~n", [Addr, Port, lists:flatten(TrapStr)]),
348
handle_snmp_callback(handle_inform, {Addr, Port, SnmpInform}) ->
349
{ES, EI, VBs} = SnmpInform,
350
io:format("*** Received INFORM ***"
354
"~n Error Status: ~w"
357
"~n", [Addr, Port, ES, EI, VBs]),
359
handle_snmp_callback(handle_report, {Addr, Port, SnmpReport}) ->
360
{ES, EI, VBs} = SnmpReport,
361
io:format("*** Received REPORT ***"
365
"~n Error Status: ~w"
368
"~n", [Addr, Port, ES, EI, VBs]),
370
handle_snmp_callback(BadTag, Crap) ->
371
io:format("*** Received crap ***"
374
"~n", [BadTag, Crap]),
380
throw({error, Reason}).
384
catch error_logger:error_msg("*** TEST-MANAGER: " ++ F ++ "~n", A).
388
gen_server:call(?SERVER, Req, infinity).
391
gen_server:cast(?SERVER, Msg).
394
%% ========================================================================
395
%% Misc internal utility functions
396
%% ========================================================================
398
%% get_opt(Key, Opts) ->
399
%% case lists:keysearch(Key, 1, Opts) of
400
%% {value, {Key, Val}} ->
403
%% throw({error, {missing_mandatory, Key}})
406
get_opt(Key, Opts, Def) ->
407
case lists:keysearch(Key, 1, Opts) of
408
{value, {Key, Val}} ->
415
%% ========================================================================
416
%% SNMPM user callback functions
417
%% ========================================================================
419
handle_error(ReqId, Reason, Server) when is_pid(Server) ->
420
report_callback(Server, handle_error, {ReqId, Reason}),
424
handle_agent(Addr, Port, SnmpInfo, Server) when is_pid(Server) ->
425
report_callback(Server, handle_agent, {Addr, Port, SnmpInfo}),
429
handle_pdu(Addr, Port, ReqId, SnmpResponse, Server) when is_pid(Server) ->
430
report_callback(Server, handle_pdu, {Addr, Port, ReqId, SnmpResponse}),
434
handle_trap(Addr, Port, SnmpTrap, Server) when is_pid(Server) ->
435
report_callback(Server, handle_trap, {Addr, Port, SnmpTrap}),
438
handle_inform(Addr, Port, SnmpInform, Server) when is_pid(Server) ->
439
report_callback(Server, handle_inform, {Addr, Port, SnmpInform}),
443
handle_report(Addr, Port, SnmpReport, Server) when is_pid(Server) ->
444
report_callback(Server, handle_inform, {Addr, Port, SnmpReport}),
447
report_callback(Pid, Tag, Info) ->
448
Pid ! {snmp_callback, Tag, Info}.