1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 1996-2019. 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-module(snmp_standard_mib).
21
22%%%-----------------------------------------------------------------
23%%% This module implements the configure- and reinit-functions
24%%% for the STANDARD-MIB and SNMPv2-MIB.
25%%%-----------------------------------------------------------------
26
27-include("snmp_types.hrl").
28-include("STANDARD-MIB.hrl").
29
30-include("snmpa_internal.hrl").
31-define(VMODULE,"STANDARD-MIB").
32-include("snmp_verbosity.hrl").
33
34-define(enabled, 1).
35-define(disabled, 2).
36
37%% External exports
38%% Avoid warning for local function error/1 clashing with autoimported BIF.
39-compile({no_auto_import,[error/1]}).
40-export([configure/1, reconfigure/1, reset/0, sys_up_time/0, sys_up_time/1,
41	 snmp_enable_authen_traps/1, snmp_enable_authen_traps/2,
42	 sys_object_id/1, sys_object_id/2, sys_or_table/3,
43	 variable_func/1, variable_func/2,
44	 inc/1, inc/2]).
45-export([sysDescr/1, sysContact/1, sysName/1, sysLocation/1,
46	 sysServices/1, sysUpTime/1, snmpEnableAuthenTraps/1,
47	 sysObjectID/1,
48	 snmpInPkts/1, snmpOutPkts/1,
49	 snmpInBadVersions/1,
50	 snmpInBadCommunityNames/1, snmpInBadCommunityUses/1,
51	 snmpInASNParseErrs/1,
52	 snmpInTooBigs/1,
53	 snmpInNoSuchNames/1, snmpInBadValues/1,
54	 snmpInReadOnlys/1, snmpInGenErrs/1,
55	 snmpInTotalReqVars/1, snmpInTotalSetVars/1,
56	 snmpInGetRequests/1, snmpInSetRequests/1,
57	 snmpInGetNexts/1,
58	 snmpInGetResponses/1, snmpInTraps/1,
59	 snmpOutTooBigs/1,
60	 snmpOutNoSuchNames/1,
61	 snmpOutBadValues/1,
62	 snmpOutGenErrs/1,
63	 snmpOutGetRequests/1, snmpOutSetRequests/1,
64	 snmpOutGetNexts/1,
65	 snmpOutGetResponses/1,
66	 snmpOutTraps/1]).
67-export([dummy/1, snmp_set_serial_no/1, snmp_set_serial_no/2]).
68-export([add_agent_caps/2, del_agent_caps/1, get_agent_caps/0]).
69-export([check_standard/1]).
70
71
72%%-----------------------------------------------------------------
73%% Func: configure/1
74%% Args: Dir is the directory with trailing dir_separator where
75%%       the configuration files can be found.
76%% Purpose: Reads the config-files for the standard mib, and
77%%          inserts the data.  Persistent data that is already
78%%          present is *not* changed!  (use reconfigure for that)
79%% Returns: ok
80%% Fails: exit(configuration_error)
81%%-----------------------------------------------------------------
82configure(Dir) ->
83    case (catch do_configure(Dir)) of
84	ok ->
85	    ok;
86	{error, Reason} ->
87	    ?vinfo("configure error: ~p", [Reason]),
88	    config_err("configure failed: ~p", [Reason]),
89	    exit(configuration_error);
90	Error ->
91	    ?vinfo("configure failed: ~p", [Error]),
92	    config_err("configure failed: ~p", [Error]),
93	    exit(configuration_error)
94    end.
95
96do_configure(Dir) ->
97    case snmpa_agent:get_agent_mib_storage() of
98        mnesia ->
99            ok;
100        _ ->
101            Standard = read_standard(Dir),
102            lists:map(fun maybe_create_persistent_var/1, Standard)
103    end,
104    snmpa_local_db:variable_set({next_sys_or_index, volatile}, 1),
105    %% sysORTable is always volatile
106    snmp_generic:table_func(new, {sysORTable, volatile}),
107    ok.
108
109
110%%-----------------------------------------------------------------
111%% Func: reconfigure/1
112%% Args: Dir is the directory with trailing dir_separator where
113%%       the configuration files can be found.
114%% Purpose: Reads the config-files for the standard mib, and
115%%          inserts the data.  Persistent data that is already
116%%          present is deleted.  Makes sure the config file
117%%          data is used.
118%% Returns: ok
119%% Fails: exit(configuration_error)
120%%-----------------------------------------------------------------
121reconfigure(Dir) ->
122    set_sname(),
123    case (catch do_reconfigure(Dir)) of
124	ok ->
125	    ok;
126	{error, Reason} ->
127	    ?vinfo("reconfigure error: ~p", [Reason]),
128	    config_err("reconfigure failed: ~p", [Reason]),
129	    exit(configuration_error);
130	Error ->
131	    ?vinfo("reconfigure failed: ~p", [Error]),
132	    config_err("reconfigure failed: ~p", [Error]),
133	    exit(configuration_error)
134    end.
135
136do_reconfigure(Dir) ->
137    Standard = read_standard(Dir),
138    lists:map(fun create_persistent_var/1, Standard),
139    snmpa_local_db:variable_set({next_sys_or_index, volatile}, 1),
140    snmp_generic:table_func(new, {sysORTable, volatile}),
141    ok.
142
143
144%%-----------------------------------------------------------------
145%% Func: read_standard/1
146%% Args: Dir is the directory with trailing dir_separator where
147%%       the configuration files can be found.
148%% Purpose: Reads the standard configuration file.
149%% Returns: A list of standard variables
150%% Fails: If an error occurs, the process will die with Reason
151%%        configuration_error.
152%%        This file is mandatory, as it contains mandatory
153%%        config options for which there are no default values.
154%%-----------------------------------------------------------------
155read_standard(Dir) ->
156    ?vdebug("check standard config file",[]),
157    FileName = "standard.conf",
158    Gen =
159	fun (D, Reason) ->
160		throw(
161		  {error,
162		   {failed_reading_config_file,
163		    D, FileName, list_dir(Dir), Reason}})
164	end,
165    Order  = fun snmp_conf:no_order/2,
166    Check  = fun (Entry, State) -> {check_standard(Entry), State} end,
167    Filter = fun sort_standard/1,
168    [Standard] =
169	snmp_conf:read_files(Dir, [{FileName, Gen, Order, Check, Filter}]),
170    Standard.
171
172list_dir(Dir) ->
173    case file:list_dir(Dir) of
174	{ok, Files} ->
175	    Files;
176	Error ->
177	    Error
178    end.
179
180
181%%-----------------------------------------------------------------
182%% Make sure that each mandatory standard attribute is present, and
183%% provide default values for the other non-present attributes.
184%%-----------------------------------------------------------------
185sort_standard(L) ->
186    Mand = [{sysContact, {value, ""}},
187	    {sysDescr, {value, ""}},
188	    {sysLocation, {value, ""}},
189	    {sysName, {value, ""}},
190	    {sysObjectID, mandatory},
191	    {sysServices, mandatory},
192	    {snmpEnableAuthenTraps, mandatory}],
193    {ok, L2} = snmp_conf:check_mandatory(L, Mand),
194    lists:keysort(1, L2).
195
196
197%%-----------------------------------------------------------------
198%%  Standard
199%%  {Name, Value}.
200%%-----------------------------------------------------------------
201check_standard({sysDescr,    Value}) -> snmp_conf:check_string(Value);
202check_standard({sysObjectID, Value}) -> snmp_conf:check_oid(Value);
203check_standard({sysContact,  Value}) -> snmp_conf:check_string(Value);
204check_standard({sysName,     Value}) -> snmp_conf:check_string(Value);
205check_standard({sysLocation, Value}) -> snmp_conf:check_string(Value);
206check_standard({sysServices, Value}) -> snmp_conf:check_integer(Value);
207check_standard({snmpEnableAuthenTraps, Value}) ->
208    Atoms = [{enabled,  ?snmpEnableAuthenTraps_enabled},
209	     {disabled, ?snmpEnableAuthenTraps_disabled}],
210    {ok, Val} = snmp_conf:check_atom(Value, Atoms),
211    {ok, {snmpEnableAuthenTraps, Val}};
212check_standard({Attrib, _Value}) -> error({unknown_attribute, Attrib});
213check_standard(X) -> error({invalid_standard_specification, X}).
214
215
216%%-----------------------------------------------------------------
217%% Func: reset/0
218%% Purpose: Resets all counters (sets them to 0).
219%%-----------------------------------------------------------------
220reset() ->
221    snmpa_mpd:reset().
222
223maybe_create_persistent_var({Var, Val}) ->
224    VarDB = db(Var),
225    case snmp_generic:variable_get(VarDB) of
226	{value, _} -> ok;
227	_ -> snmp_generic:variable_set(VarDB, Val)
228    end.
229
230create_persistent_var({Var, Val}) ->
231    snmp_generic:variable_set(db(Var), Val).
232
233variable_func(_Op) -> ok.
234
235variable_func(get, Name) ->
236    [{_, Val}] = ets:lookup(snmp_agent_table, Name),
237    {value, Val}.
238
239
240%%-----------------------------------------------------------------
241%%  inc(VariableName) increments the variable (Counter) in
242%%  the local mib. (e.g. snmpInPkts)
243%%-----------------------------------------------------------------
244inc(Name) -> inc(Name, 1).
245inc(Name, N) -> ets:update_counter(snmp_agent_table, Name, N).
246
247
248sysDescr(print) ->
249    VarAndValue = [{sysDescr,  sysDescr(get)}],
250    snmpa_mib_lib:print_variables(VarAndValue);
251
252sysDescr(get) ->
253    VarDB = db(sysDescr),
254    snmp_generic:variable_get(VarDB).
255
256
257sysContact(print) ->
258    VarAndValue = [{sysContact,  sysContact(get)}],
259    snmpa_mib_lib:print_variables(VarAndValue);
260
261sysContact(get) ->
262    VarDB = db(sysContact),
263    snmp_generic:variable_get(VarDB).
264
265
266sysName(print) ->
267    VarAndValue = [{sysName,  sysName(get)}],
268    snmpa_mib_lib:print_variables(VarAndValue);
269
270sysName(get) ->
271    VarDB = db(sysName),
272    snmp_generic:variable_get(VarDB).
273
274
275sysLocation(print) ->
276    VarAndValue = [{sysLocation,  sysLocation(get)}],
277    snmpa_mib_lib:print_variables(VarAndValue);
278
279sysLocation(get) ->
280    VarDB = db(sysLocation),
281    snmp_generic:variable_get(VarDB).
282
283
284sysServices(print) ->
285    VarAndValue = [{sysServices,  sysServices(get)}],
286    snmpa_mib_lib:print_variables(VarAndValue);
287
288sysServices(get) ->
289    VarDB = db(sysServices),
290    snmp_generic:variable_get(VarDB).
291
292
293snmpInPkts(print) ->
294    gen_counter(print, snmpInPkts);
295snmpInPkts(get) ->
296    gen_counter(get, snmpInPkts).
297
298
299snmpOutPkts(print) ->
300    gen_counter(print, snmpOutPkts);
301snmpOutPkts(get) ->
302    gen_counter(get, snmpOutPkts).
303
304
305snmpInASNParseErrs(print) ->
306    gen_counter(print, snmpInASNParseErrs);
307snmpInASNParseErrs(get) ->
308    gen_counter(get, snmpInASNParseErrs).
309
310
311snmpInBadCommunityNames(print) ->
312    gen_counter(print, snmpInBadCommunityNames);
313snmpInBadCommunityNames(get) ->
314    gen_counter(get, snmpInBadCommunityNames).
315
316
317snmpInBadCommunityUses(print) ->
318    gen_counter(print, snmpInBadCommunityUses);
319
320snmpInBadCommunityUses(get) ->
321    gen_counter(get, snmpInBadCommunityUses).
322
323
324snmpInBadVersions(print) ->
325    gen_counter(print, snmpInBadVersions);
326snmpInBadVersions(get) ->
327    gen_counter(get, snmpInBadVersions).
328
329
330snmpInTooBigs(print) ->
331    gen_counter(print, snmpInTooBigs);
332snmpInTooBigs(get) ->
333    gen_counter(get, snmpInTooBigs).
334
335
336snmpInNoSuchNames(print) ->
337    gen_counter(print, snmpInNoSuchNames);
338snmpInNoSuchNames(get) ->
339    gen_counter(get, snmpInNoSuchNames).
340
341
342snmpInBadValues(print) ->
343    gen_counter(print, snmpInBadValues);
344snmpInBadValues(get) ->
345    gen_counter(get, snmpInBadValues).
346
347
348snmpInReadOnlys(print) ->
349    gen_counter(print, snmpInReadOnlys);
350snmpInReadOnlys(get) ->
351    gen_counter(get, snmpInReadOnlys).
352
353
354snmpInGenErrs(print) ->
355    gen_counter(print, snmpInGenErrs);
356snmpInGenErrs(get) ->
357    gen_counter(get, snmpInGenErrs).
358
359
360snmpInTotalReqVars(print) ->
361    gen_counter(print, snmpInTotalReqVars);
362snmpInTotalReqVars(get) ->
363    gen_counter(get, snmpInTotalReqVars).
364
365
366snmpInTotalSetVars(print) ->
367    gen_counter(print, snmpInTotalSetVars);
368snmpInTotalSetVars(get) ->
369    gen_counter(get, snmpInTotalSetVars).
370
371
372snmpInGetRequests(print) ->
373    gen_counter(print, snmpInGetRequests);
374snmpInGetRequests(get) ->
375    gen_counter(get, snmpInGetRequests).
376
377
378snmpInSetRequests(print) ->
379    gen_counter(print, snmpInSetRequests);
380snmpInSetRequests(get) ->
381    gen_counter(get, snmpInSetRequests).
382
383
384snmpInGetNexts(print) ->
385    gen_counter(print, snmpInGetNexts);
386snmpInGetNexts(get) ->
387    gen_counter(get, snmpInGetNexts).
388
389
390snmpInGetResponses(print) ->
391    gen_counter(print, snmpInGetResponses);
392snmpInGetResponses(get) ->
393    gen_counter(get, snmpInGetResponses).
394
395
396snmpInTraps(print) ->
397    gen_counter(print, snmpInTraps);
398snmpInTraps(get) ->
399    gen_counter(get, snmpInTraps).
400
401
402snmpOutTooBigs(print) ->
403    gen_counter(print, snmpOutTooBigs);
404snmpOutTooBigs(get) ->
405    gen_counter(get, snmpOutTooBigs).
406
407
408snmpOutNoSuchNames(print) ->
409    gen_counter(print, snmpOutNoSuchNames);
410snmpOutNoSuchNames(get) ->
411    gen_counter(get, snmpOutNoSuchNames).
412
413
414snmpOutBadValues(print) ->
415    gen_counter(print, snmpOutBadValues);
416snmpOutBadValues(get) ->
417    gen_counter(get, snmpOutBadValues).
418
419
420snmpOutGenErrs(print) ->
421    gen_counter(print, snmpOutGenErrs);
422snmpOutGenErrs(get) ->
423    gen_counter(get, snmpOutGenErrs).
424
425
426snmpOutGetRequests(print) ->
427    gen_counter(print, snmpOutGetRequests);
428snmpOutGetRequests(get) ->
429    gen_counter(get, snmpOutGetRequests).
430
431
432snmpOutSetRequests(print) ->
433    gen_counter(print, snmpOutSetRequests);
434snmpOutSetRequests(get) ->
435    gen_counter(get, snmpOutSetRequests).
436
437
438snmpOutGetNexts(print) ->
439    gen_counter(print, snmpOutGetNexts);
440snmpOutGetNexts(get) ->
441    gen_counter(get, snmpOutGetNexts).
442
443
444snmpOutGetResponses(print) ->
445    gen_counter(print, snmpOutGetResponses);
446snmpOutGetResponses(get) ->
447    gen_counter(get, snmpOutGetResponses).
448
449
450snmpOutTraps(print) ->
451    gen_counter(print, snmpOutTraps);
452snmpOutTraps(get) ->
453    gen_counter(get, snmpOutTraps).
454
455
456gen_counter(print, Counter) ->
457    Val         = gen_counter(get, Counter),
458    VarAndValue = [{Counter, Val}],
459    snmpa_mib_lib:print_variables(VarAndValue);
460
461gen_counter(get, Counter) ->
462    variable_func(get, Counter).
463
464
465%%-----------------------------------------------------------------
466%% This is the instrumentation function for sysUpTime.
467%%-----------------------------------------------------------------
468sysUpTime(print) ->
469    sys_up_time(print);
470sysUpTime(get) ->
471    sys_up_time(get).
472
473sys_up_time() ->
474    snmpa:sys_up_time().
475
476sys_up_time(print) ->
477    VarAndValue = [{sysUpTime,  sys_up_time(get)}],
478    snmpa_mib_lib:print_variables(VarAndValue);
479
480sys_up_time(get) ->
481    {value, snmpa:sys_up_time()}.
482
483
484%%-----------------------------------------------------------------
485%% This is the instrumentation function for snmpEnableAuthenTraps
486%%-----------------------------------------------------------------
487
488snmpEnableAuthenTraps(print) ->
489    snmp_enable_authen_traps(print);
490snmpEnableAuthenTraps(get) ->
491    snmp_enable_authen_traps(get).
492
493
494snmp_enable_authen_traps(print) ->
495    VarAndValue = [{snmpEnableAuthenTraps,  snmp_enable_authen_traps(get)}],
496    snmpa_mib_lib:print_variables(VarAndValue);
497
498snmp_enable_authen_traps(new) ->
499    snmp_generic:variable_func(new, db(snmpEnableAuthenTraps));
500
501snmp_enable_authen_traps(delete) ->
502    ok;
503
504snmp_enable_authen_traps(get) ->
505    snmp_generic:variable_func(get, db(snmpEnableAuthenTraps)).
506
507snmp_enable_authen_traps(set, NewVal) ->
508    snmp_generic:variable_func(set, NewVal, db(snmpEnableAuthenTraps)).
509
510
511%%-----------------------------------------------------------------
512%% This is the instrumentation function for sysObjectID
513%%-----------------------------------------------------------------
514sysObjectID(print) ->
515    sys_object_id(print);
516sysObjectID(get) ->
517    sys_object_id(get).
518
519sys_object_id(print) ->
520    VarAndValue = [{sysObjectID,  sys_object_id(get)}],
521    snmpa_mib_lib:print_variables(VarAndValue);
522
523sys_object_id(new) ->
524    snmp_generic:variable_func(new, db(sysObjectID));
525
526sys_object_id(delete) ->
527    ok;
528
529sys_object_id(get) ->
530    snmp_generic:variable_func(get, db(sysObjectID)).
531
532sys_object_id(set, NewVal) ->
533    snmp_generic:variable_func(set, NewVal, db(sysObjectID)).
534
535
536%%-----------------------------------------------------------------
537%% This is a dummy instrumentation function for objects like
538%% snmpTrapOID, that is accessible-for-notify, with different
539%% values each time.  This function will only be called with
540%% new/delete.
541%%-----------------------------------------------------------------
542dummy(_Op) -> ok.
543
544
545%%-----------------------------------------------------------------
546%% This is the instrumentation function for snmpSetSerialNo.
547%% It is always volatile.
548%%-----------------------------------------------------------------
549snmp_set_serial_no(new) ->
550    snmp_generic:variable_func(new, {snmpSetSerialNo, volatile}),
551    ?SNMP_RAND_SEED(),
552    %% rand:seed(exrop,
553    %%           {erlang:phash2([node()]),
554    %%            erlang:monotonic_time(),
555    %%            erlang:unique_integer()}),
556    Val = rand:uniform(2147483648) - 1,
557    snmp_generic:variable_func(set, Val, {snmpSetSerialNo, volatile});
558
559snmp_set_serial_no(delete) ->
560    ok;
561
562snmp_set_serial_no(get) ->
563    snmp_generic:variable_func(get, {snmpSetSerialNo, volatile}).
564
565snmp_set_serial_no(is_set_ok, NewVal) ->
566    case snmp_generic:variable_func(get, {snmpSetSerialNo, volatile}) of
567	{value, NewVal} -> noError;
568	_ -> inconsistentValue
569    end;
570snmp_set_serial_no(set, NewVal) ->
571    snmp_generic:variable_func(set, (NewVal + 1) rem 2147483648,
572			       {snmpSetSerialNo, volatile}).
573
574
575%%-----------------------------------------------------------------
576%% This is the instrumentation function for sysOrTable
577%%-----------------------------------------------------------------
578sys_or_table(Op, RowIndex, Cols) ->
579    snmp_generic:table_func(Op, RowIndex, Cols, {sysORTable, volatile}).
580
581add_agent_caps(Oid, Descr) when is_list(Oid) andalso is_list(Descr) ->
582    {value, Next} = snmpa_local_db:variable_get({next_sys_or_index, volatile}),
583    snmpa_local_db:variable_set({next_sys_or_index, volatile}, Next+1),
584    SysUpTime = sys_up_time(),
585    Row = {Next, Oid, Descr, SysUpTime},
586    snmpa_local_db:table_create_row({sysORTable, volatile}, [Next], Row),
587    snmpa_local_db:variable_set({sysORLastChange, volatile}, SysUpTime),
588    Next.
589
590del_agent_caps(Index) ->
591    snmpa_local_db:table_delete_row({sysORTable, volatile}, [Index]),
592    snmpa_local_db:variable_set({sysORLastChange, volatile}, sys_up_time()).
593
594get_agent_caps() ->
595    snmpa_local_db:match({sysORTable, volatile}, {'$1', '$2', '$3', '$4'}).
596
597
598db(Var) -> snmpa_agent:db(Var).
599
600
601%% -----
602
603set_sname() ->
604    set_sname(get(sname)).
605
606set_sname(undefined) ->
607    put(sname,conf);
608set_sname(_) -> %% Keep it, if already set.
609    ok.
610
611error(Reason) ->
612    throw({error, Reason}).
613
614config_err(F, A) ->
615    snmpa_error:config_err("[STANDARD-MIB] " ++ F, A).
616