1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2005-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%----------------------------------------------------------------------
22%% Purpose: Utility functions for the (snmp manager) user test(s).
23%%----------------------------------------------------------------------
24
25-module(snmp_manager_user).
26
27-behaviour(snmpm_user).
28%% -behaviour(snmpm_user_old).
29
30
31%%----------------------------------------------------------------------
32%% Include files
33%%----------------------------------------------------------------------
34-include_lib("common_test/include/ct.hrl").
35-include("snmp_test_lib.hrl").
36
37
38%%----------------------------------------------------------------------
39%% External exports
40%%----------------------------------------------------------------------
41-export([
42         start_link/0, start_link/1, start_link/2,
43	 start/0, start/1, start/2,
44	 stop/0,
45	 info/0,
46	 system_info/0,
47	 simulate_crash/1,
48	 register_agent/2,
49	 unregister_agent/1,
50	 agent_info/2,
51	 update_agent_info/3,
52	 which_all_agents/0, which_own_agents/0,
53	 load_mib/1, unload_mib/1,
54         sync_get2/3,
55         async_get2/3,
56         sync_get_next2/3,
57         async_get_next2/3,
58         sync_set2/3,
59         async_set2/3,
60         sync_get_bulk2/5,
61         async_get_bulk2/5,
62	 name_to_oid/1, oid_to_name/1,
63	 purify_oid/1
64        ]).
65
66
67%%----------------------------------------------------------------------
68%% Internal exports
69%%----------------------------------------------------------------------
70
71-export([
72	 main/4
73        ]).
74
75-export([
76	 handle_error/3,
77         handle_agent/5,
78         handle_pdu/4,
79         handle_trap/3,
80         handle_inform/3,
81         handle_report/3
82	]).
83
84
85-define(SERVER, ?MODULE).
86
87-record(state, {parent, id, reqs = []}).
88%% -record(request, {from, ref, tmr, req_id, type}).
89
90
91%%----------------------------------------------------------------------
92%% The user API
93%%----------------------------------------------------------------------
94
95start() ->
96    start(self()).
97
98start(Parent) ->
99    start(Parent, test_user).
100
101start(Parent, Id) ->
102    proc_lib:start(?MODULE, main, [true, Parent, self(), Id]).
103
104start_link() ->
105    start_link(self()).
106start_link(Parent) ->
107    start_link(Parent, test_user).
108
109start_link(Parent, Id) ->
110    proc_lib:start_link(?MODULE, main, [true, Parent, self(), Id]).
111
112stop() ->
113    MRef = erlang:monitor(process, ?SERVER),
114    cast(stop),
115    receive {'DOWN', MRef, _, _, Info} ->
116	    case Info of
117		noproc ->
118		    ok;
119		noconnection ->
120		    ok;
121		normal ->
122		    ok
123	    end
124    end.
125
126info() ->
127    call(info).
128
129system_info() ->
130    call(system_info).
131
132simulate_crash(Reason) ->
133    call({simulate_crash, Reason}).
134
135register_agent(TargetName, Config)
136  when is_list(TargetName) andalso is_list(Config) ->
137    call({register_agent, TargetName, Config}).
138
139unregister_agent(TargetName) ->
140    call({unregister_agent, TargetName}).
141
142agent_info(TargetName, Item) ->
143    call({agent_info, TargetName, Item}).
144
145update_agent_info(TargetName, Item, Val) ->
146    call({update_agent_info, TargetName, Item, Val}).
147
148which_all_agents() ->
149    call(which_all_agents).
150
151which_own_agents() ->
152    call(which_own_agents).
153
154load_mib(Mib) ->
155    call({load_mib, Mib}).
156
157unload_mib(Mib) ->
158    call({unload_mib, Mib}).
159
160%% --
161
162sync_get2(TargetName, Oids, SendOpts) ->
163    call({sync_get2, TargetName, Oids, SendOpts}).
164
165
166%% --
167
168async_get2(TargetName, Oids, SendOpts) ->
169    call({async_get2, TargetName, Oids, SendOpts}).
170
171%% --
172
173sync_get_next2(TargetName, Oids, SendOpts) ->
174    call({sync_get_next2, TargetName, Oids, SendOpts}).
175
176%% --
177
178async_get_next2(TargetName, Oids, SendOpts) ->
179    call({async_get_next2, TargetName, Oids, SendOpts}).
180
181%% --
182
183sync_set2(TargetName, VAV, SendOpts) ->
184    call({sync_set2, TargetName, VAV, SendOpts}).
185
186%% --
187
188async_set2(TargetName, VAV, SendOpts) ->
189    call({async_set2, TargetName, VAV, SendOpts}).
190
191%% --
192
193sync_get_bulk2(TargetName, NonRep, MaxRep, Oids, SendOpts) ->
194    call({sync_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts}).
195
196%% --
197
198async_get_bulk2(TargetName, NonRep, MaxRep, Oids, SendOpts) ->
199    call({async_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts}).
200
201%% --
202
203name_to_oid(Name) ->
204    call({name_to_oid, Name}).
205
206oid_to_name(Oid) ->
207    call({oid_to_name, Oid}).
208
209purify_oid(Oid) ->
210    call({purify_oid, Oid}).
211
212
213%%----------------------------------------------------------------------
214
215main(Debug, Parent, Starter, Id) ->
216    put(debug, Debug),
217    d("main -> entry with"
218      "~n   Parent:  ~p"
219      "~n   Starter: ~p"
220      "~n   Id:      ~p", [Parent, Starter, Id]),
221    case (catch do_init(Id)) of
222	ok ->
223	    proc_lib:init_ack(Starter, {ok, self()}),
224	    loop(#state{parent = Parent, id = Id});
225	Error ->
226	    d("main -> error: "
227	      "~p", [Error]),
228	    proc_lib:init_ack(Starter, Error)
229    end.
230
231do_init(Id) ->
232    erlang:register(?SERVER, self()),
233    snmpm:register_user(Id, ?MODULE, self()).
234
235
236%%----------------------------------------------------------------------
237
238loop(#state{parent = Parent, id = Id} = S) ->
239    d("loop -> entry"),
240    receive
241	{stop, _From} ->
242	    d("loop -> received stop request"),
243	    exit(normal);
244
245	{{simulate_crash, Reason}, From, Ref} ->
246	    d("loop -> received simulate_crash request"),
247	    reply(From, ok, Ref),
248	    exit(Reason);
249
250	{info, From, Ref} ->
251	    d("loop -> received info request"),
252	    Res = snmpm:info(),
253	    reply(From, Res, Ref),
254	    loop(S);
255
256	{system_info, From, Ref} ->
257	    d("loop -> received system_info request"),
258	    Res = snmpm_config:system_info(),
259	    reply(From, Res, Ref),
260	    loop(S);
261
262	{{register_agent, TargetName, Conf}, From, Ref} ->
263	    d("loop -> received register_agent request"),
264	    Res = snmpm:register_agent(Id, TargetName, Conf),
265	    reply(From, Res, Ref),
266	    loop(S);
267
268	{{unregister_agent, TargetName}, From, Ref} ->
269	    d("loop -> received unregister_agent request"),
270	    Res = snmpm:unregister_agent(Id, TargetName),
271	    reply(From, Res, Ref),
272	    loop(S);
273
274	{{agent_info, TargetName, Item}, From, Ref} ->
275	   d("loop -> received agent_info request with"
276	     "~n   TargetName: ~p"
277	     "~n   Item:       ~p", [TargetName, Item]),
278	    Res = snmpm:agent_info(TargetName, Item),
279	   d("loop -> agent_info for ~p"
280	     "~n   Res: ~p", [Item, Res]),
281	    reply(From, Res, Ref),
282	    loop(S);
283
284	{{update_agent_info, TargetName, Item, Val}, From, Ref} ->
285	   d("loop -> received update_agent_info request with"
286	     "~n   TargetName: ~p"
287	     "~n   Item:       ~p"
288	     "~n   Val:        ~p", [TargetName, Item, Val]),
289	    Res = snmpm:update_agent_info(Id, TargetName, Item, Val),
290	    reply(From, Res, Ref),
291	    loop(S);
292
293	{which_all_agents, From, Ref} ->
294	    d("loop -> received which_all_agents request"),
295	    Res = snmpm:which_agents(),
296	    reply(From, Res, Ref),
297	    loop(S);
298
299	{which_own_agents, From, Ref} ->
300	    d("loop -> received which_own_agents request"),
301	    Res = snmpm:which_agents(Id),
302	    reply(From, Res, Ref),
303	    loop(S);
304
305	{{load_mib, Mib}, From, Ref} ->
306	    d("loop -> received load_mib request"),
307	    Res = snmpm:load_mib(Mib),
308	    reply(From, Res, Ref),
309	    loop(S);
310
311	{{unload_mib, Mib}, From, Ref} ->
312	    d("loop -> received unload_mib request"),
313	    Res = snmpm:unload_mib(Mib),
314	    reply(From, Res, Ref),
315	    loop(S);
316
317
318	%%
319	%% -- (sync) get-request --
320	%%
321
322	{{sync_get2, TargetName, Oids, SendOpts}, From, Ref}
323	  when is_list(TargetName) ->
324	    d("loop -> received sync_get2 request with"
325	      "~n   TargetName: ~p"
326	      "~n   Oids:       ~p"
327	      "~n   SendOpts:   ~p", [TargetName, Oids, SendOpts]),
328	    Res = snmpm:sync_get2(Id, TargetName, Oids, SendOpts),
329	    reply(From, Res, Ref),
330	    loop(S);
331
332
333	%%
334	%% -- (async) get-request --
335	%%
336
337	{{async_get2, TargetName, Oids, SendOpts}, From, Ref}
338	  when is_list(TargetName) ->
339	    d("loop -> received async_get2 request with"
340	      "~n   TargetName: ~p"
341	      "~n   Oids:       ~p"
342	      "~n   SendOpts:   ~p", [TargetName, Oids, SendOpts]),
343	    Res = snmpm:async_get2(Id, TargetName, Oids, SendOpts),
344	    reply(From, Res, Ref),
345	    loop(S);
346
347
348	%%
349	%% -- (sync) get_next-request --
350	%%
351
352	{{sync_get_next2, TargetName, Oids, SendOpts}, From, Ref}
353	  when is_list(TargetName) ->
354	    d("loop -> received sync_get_next2 request with"
355	      "~n   TargetName: ~p"
356	      "~n   Oids:       ~p"
357	      "~n   SendOpts:   ~p", [TargetName, Oids, SendOpts]),
358	    Res = snmpm:sync_get_next2(Id, TargetName, Oids, SendOpts),
359	    reply(From, Res, Ref),
360	    loop(S);
361
362
363	%%
364	%% -- (async) get_next-request --
365	%%
366
367	{{async_get_next2, TargetName, Oids, SendOpts}, From, Ref}
368	  when is_list(TargetName) ->
369	    d("loop -> received async_get_next2 request with"
370	      "~n   TargetName: ~p"
371	      "~n   Oids:       ~p"
372	      "~n   SendOpts:   ~p", [TargetName, Oids, SendOpts]),
373	    Res = snmpm:async_get_next2(Id, TargetName, Oids, SendOpts),
374	    reply(From, Res, Ref),
375	    loop(S);
376
377
378	%%
379	%% -- (sync) set-request --
380	%%
381
382	{{sync_set2, TargetName, VAV, SendOpts}, From, Ref}
383	  when is_list(TargetName) ->
384	    d("loop -> received sync_set2 request with"
385	      "~n   TargetName: ~p"
386	      "~n   VAV:        ~p"
387	      "~n   SendOpts:   ~p", [TargetName, VAV, SendOpts]),
388	    Res = snmpm:sync_set2(Id, TargetName, VAV, SendOpts),
389	    reply(From, Res, Ref),
390	    loop(S);
391
392
393	%%
394	%% -- (async) set-request --
395	%%
396
397	{{async_set2, TargetName, VAV, SendOpts}, From, Ref}
398	  when is_list(TargetName) ->
399	    d("loop -> received async_set2 request with"
400	      "~n   TargetName: ~p"
401	      "~n   VAV:        ~p"
402	      "~n   SendOpts:   ~p", [TargetName, VAV, SendOpts]),
403	    Res = snmpm:async_set2(Id, TargetName, VAV, SendOpts),
404	    reply(From, Res, Ref),
405	    loop(S);
406
407
408	%%
409	%% -- (sync) get-bulk-request --
410	%%
411
412	{{sync_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts}, From, Ref}
413	  when is_list(TargetName) ->
414	    d("loop -> received sync_get_bulk request with"
415	      "~n   TargetName: ~p"
416	      "~n   NonRep:     ~w"
417	      "~n   MaxRep:     ~w"
418	      "~n   Oids:       ~p"
419	      "~n   SendOpts:   ~p",
420	      [TargetName, NonRep, MaxRep, Oids, SendOpts]),
421	    Res = snmpm:sync_get_bulk2(Id, TargetName,
422				       NonRep, MaxRep, Oids, SendOpts),
423	    reply(From, Res, Ref),
424	    loop(S);
425
426
427	%%
428	%% -- (async) get-bulk-request --
429	%%
430
431	{{async_get_bulk2, TargetName, NonRep, MaxRep, Oids, SendOpts},
432	 From, Ref} when is_list(TargetName) ->
433	    d("loop -> received async_get_bulk2 request with"
434	      "~n   TargetName: ~p"
435	      "~n   NonRep:     ~w"
436	      "~n   MaxRep:     ~w"
437	      "~n   Oids:       ~p"
438	      "~n   SendOpts:   ~p",
439	      [TargetName, NonRep, MaxRep, Oids, SendOpts]),
440	    Res = snmpm:async_get_bulk2(Id, TargetName,
441					NonRep, MaxRep, Oids, SendOpts),
442	    reply(From, Res, Ref),
443	    loop(S);
444
445
446	%%
447	%% -- logical name translation --
448	%%
449
450	{{name_to_oid, Name}, From, Ref} ->
451	    d("loop -> received name_to_oid request for"
452	      "~n   Name: ~p", [Name]),
453	    Res = snmpm:name_to_oid(Name),
454	    reply(From, Res, Ref),
455	    loop(S);
456
457	{{oid_to_name, Oid}, From, Ref} ->
458	    d("loop -> received oid_to_name request for"
459	      "~n   Oid: ~p", [Oid]),
460	    Res = snmpm:oid_to_name(Oid),
461	    reply(From, Res, Ref),
462	    loop(S);
463
464	{{purify_oid, Oid}, From, Ref} ->
465	    d("loop -> received purify_oid request for"
466	      "~n   Oid: ~p", [Oid]),
467	    Res = do_purify_oid(Oid),
468	    reply(From, Res, Ref),
469	    loop(S);
470
471
472	%% SNMP manager callback messages (from our callback API):
473
474	{handle_error, _Pid, ReqId, Reason} ->
475	    d("loop -> received error callback from manager for ~w:"
476	      "~n   ~p", [ReqId, Reason]),
477	    Parent ! {async_event, ReqId, {error, Reason}},
478	    loop(S);
479
480	{handle_agent, _Pid, Addr, Port, SnmpInfo} ->
481	    d("loop -> received agent callback from manager for ~n   ~p:~w",
482	      [Addr, Port]),
483	    Parent ! {async_event, {Addr, Port}, {agent, SnmpInfo}},
484	    loop(S);
485
486	{handle_pdu, _Pid, _TargetName, ReqId, SnmpResponse} ->
487	    d("loop -> received pdu callback from manager for ~w", [ReqId]),
488	    Parent ! {async_event, ReqId, {pdu, SnmpResponse}},
489	    loop(S);
490
491	{handle_trap, _Pid, TargetName, SnmpTrap} ->
492	    d("loop -> received trap callback from manager for "
493	      "~n   ~p",
494	      "~n   ~p",
495	      [TargetName, SnmpTrap]),
496	    Parent ! {async_event, TargetName, {trap, SnmpTrap}},
497	    loop(S);
498
499	{handle_inform, Pid, TargetName, SnmpInform} ->
500	    d("loop -> received inform callback from manager for "
501	      "~n   ~p",
502	      "~n   ~p",
503	      [TargetName, SnmpInform]),
504	    Parent ! {async_event, TargetName, {inform, Pid, SnmpInform}},
505	    loop(S);
506
507	{handle_report, _Pid, TargetName, SnmpReport} ->
508	    d("loop -> received report callback from manager for "
509	      "~n   ~p",
510	      "~n   ~p",
511	      [TargetName, SnmpReport]),
512	    Parent ! {async_event, TargetName, {report, SnmpReport}},
513	    loop(S);
514
515	{handle_invalid_result, _Pid, In, Out} ->
516	    d("loop -> received invalid result callback from manager for "
517	      "~n   In:  ~p",
518	      "~n   Out: ~p", [In, Out]),
519	    info("received invalid result message: "
520		 "~n   In:  ~p"
521		 "~n   Out: ~p", [In, Out]),
522	    loop(S);
523
524	{'EXIT', Parent, Reason} ->
525	    d("received exit signal from parent: ~n~p", [Reason]),
526	    info("received exit signal from parent: ~n~p", [Reason]),
527	    exit(Reason);
528
529	Unknown ->
530	    d("received unknown message: ~n~p", [Unknown]),
531	    info("received unknown message: ~n~p", [Unknown]),
532	    loop(S)
533    end.
534
535
536%% -------------
537
538do_purify_oid([A|T]) when is_atom(A) ->
539    case snmpm:name_to_oid(A) of
540	{ok, [Oid|_]} ->
541	    verify_pure_oid(lists:flatten([Oid|T]));
542	{error, not_found} ->
543	    {error, {not_found, A}};
544	{error, _} = Error ->
545	    Error
546    end;
547do_purify_oid(L) when is_list(L) ->
548    verify_pure_oid(lists:flatten(L));
549do_purify_oid(X) ->
550    {error, {unpure_oid, X}}.
551
552verify_pure_oid([]) ->
553    [];
554verify_pure_oid([H | T]) when is_integer(H) andalso (H >= 0) ->
555    [H | verify_pure_oid(T)];
556verify_pure_oid([H | _]) ->
557    throw({error, {not_pure_oid, H}}).
558
559
560%% -------------
561
562info(F, A) ->
563    error_logger:info_msg("TEST MGR USER " ++ F ++ "~n", A).
564
565
566%% -------------
567
568call(Req) ->
569    call(Req, 5000).
570
571call(Req, To) when is_integer(To) ->
572    Ref = make_ref(),
573    ?SERVER ! {Req, self(), Ref},
574    receive
575	{Reply, Ref} ->
576	    Reply
577    after To ->
578	    {error, timeout}
579    end.
580
581reply(Pid, Reply, Ref) ->
582    d("reply -> entry with"
583      "~n   Pid:   ~p"
584      "~n   Reply: ~p"
585      "~n   Ref:   ~p", [Pid, Reply, Ref]),
586    Pid ! {Reply, Ref}.
587
588cast(Msg) ->
589    ?SERVER ! {Msg, self()},
590    ok.
591
592
593%%----------------------------------------------------------------------
594%% User callback functions:
595%%----------------------------------------------------------------------
596
597handle_error(ReqId, Reason, UserPid) ->
598    UserPid ! {handle_error, self(), ReqId, Reason},
599    ignore.
600
601
602handle_agent(Addr, Port, SnmpInfo, UserPid, UserData) ->
603    UserPid ! {handle_agent, self(), Addr, Port, SnmpInfo, UserData},
604    ignore.
605
606
607handle_pdu(TargetName, ReqId, SnmpResponse, UserPid) ->
608    UserPid ! {handle_pdu, self(), TargetName, ReqId, SnmpResponse},
609    ignore.
610
611handle_trap(TargetName, SnmpTrap, UserPid) ->
612    UserPid ! {handle_trap, self(), TargetName, SnmpTrap},
613    ignore.
614
615handle_inform(TargetName, SnmpInform, UserPid) ->
616    UserPid ! {handle_inform, self(), TargetName, SnmpInform},
617    receive
618	{handle_inform_no_response, TargetName} ->
619	    no_reply;
620	{handle_inform_response, TargetName} ->
621	    ignore
622    end.
623
624handle_report(TargetName, SnmpReport, UserPid) ->
625    UserPid ! {handle_report, self(), TargetName, SnmpReport},
626    ignore.
627
628
629%%----------------------------------------------------------------------
630%% Debug
631%%----------------------------------------------------------------------
632
633d(F) ->
634    d(F, []).
635
636d(F, A) ->
637    d(get(debug), F, A).
638
639d(true, F, A) ->
640    io:format("~w:" ++ F ++ "~n", [?SERVER|A]);
641d(_, _, _) ->
642    ok.
643