%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1996-2010. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%
-module(snmp_standard_mib).
%%%-----------------------------------------------------------------
%%% This module implements the configure- and reinit-functions
%%% for the STANDARD-MIB and SNMPv2-MIB.
%%%-----------------------------------------------------------------
-include("snmp_types.hrl").
-include("STANDARD-MIB.hrl").
-define(VMODULE,"STANDARD-MIB").
-include("snmp_verbosity.hrl").
-define(enabled, 1).
-define(disabled, 2).
%% External exports
%% Avoid warning for local function error/1 clashing with autoimported BIF.
-compile({no_auto_import,[error/1]}).
-export([configure/1, reconfigure/1, reset/0, sys_up_time/0, sys_up_time/1,
snmp_enable_authen_traps/1, snmp_enable_authen_traps/2,
sys_object_id/1, sys_object_id/2, sys_or_table/3,
variable_func/1, variable_func/2,
inc/1, inc/2]).
-export([dummy/1, snmp_set_serial_no/1, snmp_set_serial_no/2]).
-export([add_agent_caps/2, del_agent_caps/1, get_agent_caps/0]).
-export([check_standard/1]).
%%-----------------------------------------------------------------
%% Func: configure/1
%% Args: Dir is the directory with trailing dir_separator where
%% the configuration files can be found.
%% Purpose: Reads the config-files for the standard mib, and
%% inserts the data. Persistent data that is already
%% present is *not* changed! (use reconfigure for that)
%% Returns: ok
%% Fails: exit(configuration_error)
%%-----------------------------------------------------------------
configure(Dir) ->
case (catch do_configure(Dir)) of
ok ->
ok;
{error, Reason} ->
?vinfo("configure error: ~p", [Reason]),
config_err("configure failed: ~p", [Reason]),
exit(configuration_error);
Error ->
?vinfo("configure failed: ~p", [Error]),
config_err("configure failed: ~p", [Error]),
exit(configuration_error)
end.
do_configure(Dir) ->
case snmpa_agent:get_agent_mib_storage() of
mnesia ->
ok;
_ ->
Standard = read_standard(Dir),
lists:map(fun maybe_create_persistent_var/1, Standard)
end,
snmpa_local_db:variable_set({next_sys_or_index, volatile}, 1),
%% sysORTable is always volatile
snmp_generic:table_func(new, {sysORTable, volatile}),
ok.
%%-----------------------------------------------------------------
%% Func: reconfigure/1
%% Args: Dir is the directory with trailing dir_separator where
%% the configuration files can be found.
%% Purpose: Reads the config-files for the standard mib, and
%% inserts the data. Persistent data that is already
%% present is deleted. Makes sure the config file
%% data is used.
%% Returns: ok
%% Fails: exit(configuration_error)
%%-----------------------------------------------------------------
reconfigure(Dir) ->
set_sname(),
case (catch do_reconfigure(Dir)) of
ok ->
ok;
{error, Reason} ->
?vinfo("reconfigure error: ~p", [Reason]),
config_err("reconfigure failed: ~p", [Reason]),
exit(configuration_error);
Error ->
?vinfo("reconfigure failed: ~p", [Error]),
config_err("reconfigure failed: ~p", [Error]),
exit(configuration_error)
end.
do_reconfigure(Dir) ->
Standard = read_standard(Dir),
lists:map(fun create_persistent_var/1, Standard),
snmpa_local_db:variable_set({next_sys_or_index, volatile}, 1),
snmp_generic:table_func(new, {sysORTable, volatile}),
ok.
%%-----------------------------------------------------------------
%% Func: read_standard/1
%% Args: Dir is the directory with trailing dir_separator where
%% the configuration files can be found.
%% Purpose: Reads th standard configuration file.
%% Returns: A list of standard variables
%% Fails: If an error occurs, the process will die with Reason
%% configuration_error.
%%-----------------------------------------------------------------
read_standard(Dir) ->
?vdebug("check standard config file",[]),
Gen = fun(_) -> ok end,
Filter = fun(Standard) -> sort_standard(Standard) end,
Check = fun(Entry) -> check_standard(Entry) end,
[Standard] =
snmp_conf:read_files(Dir, [{Gen, Filter, Check, "standard.conf"}]),
Standard.
%%-----------------------------------------------------------------
%% Make sure that each mandatory standard attribute is present, and
%% provide default values for the other non-present attributes.
%%-----------------------------------------------------------------
sort_standard(L) ->
Mand = [{sysContact, {value, ""}},
{sysDescr, {value, ""}},
{sysLocation, {value, ""}},
{sysName, {value, ""}},
{sysObjectID, mandatory},
{sysServices, mandatory},
{snmpEnableAuthenTraps, mandatory}],
{ok, L2} = snmp_conf:check_mandatory(L, Mand),
lists:keysort(1, L2).
%%-----------------------------------------------------------------
%% Standard
%% {Name, Value}.
%%-----------------------------------------------------------------
check_standard({sysDescr, Value}) -> snmp_conf:check_string(Value);
check_standard({sysObjectID, Value}) -> snmp_conf:check_oid(Value);
check_standard({sysContact, Value}) -> snmp_conf:check_string(Value);
check_standard({sysName, Value}) -> snmp_conf:check_string(Value);
check_standard({sysLocation, Value}) -> snmp_conf:check_string(Value);
check_standard({sysServices, Value}) -> snmp_conf:check_integer(Value);
check_standard({snmpEnableAuthenTraps, Value}) ->
Atoms = [{enabled, ?snmpEnableAuthenTraps_enabled},
{disabled, ?snmpEnableAuthenTraps_disabled}],
{ok, Val} = snmp_conf:check_atom(Value, Atoms),
{ok, {snmpEnableAuthenTraps, Val}};
check_standard({Attrib, _Value}) -> error({unknown_attribute, Attrib});
check_standard(X) -> error({invalid_standard_specification, X}).
%%-----------------------------------------------------------------
%% Func: reset/0
%% Purpose: Resets all counters (sets them to 0).
%%-----------------------------------------------------------------
reset() ->
snmpa_mpd:reset().
maybe_create_persistent_var({Var, Val}) ->
VarDB = db(Var),
case snmp_generic:variable_get(VarDB) of
{value, _} -> ok;
_ -> snmp_generic:variable_set(VarDB, Val)
end.
create_persistent_var({Var, Val}) ->
snmp_generic:variable_set(db(Var), Val).
variable_func(_Op) -> ok.
variable_func(get, Name) ->
[{_, Val}] = ets:lookup(snmp_agent_table, Name),
{value, Val}.
%%-----------------------------------------------------------------
%% inc(VariableName) increments the variable (Counter) in
%% the local mib. (e.g. snmpInPkts)
%%-----------------------------------------------------------------
inc(Name) -> inc(Name, 1).
inc(Name, N) -> ets:update_counter(snmp_agent_table, Name, N).
%%-----------------------------------------------------------------
%% This is the instrumentation function for sysUpTime.
%%-----------------------------------------------------------------
sys_up_time() ->
snmpa:sys_up_time().
sys_up_time(get) ->
{value, snmpa:sys_up_time()}.
%%-----------------------------------------------------------------
%% This is the instrumentation function for snmpEnableAuthenTraps
%%-----------------------------------------------------------------
snmp_enable_authen_traps(new) ->
snmp_generic:variable_func(new, db(snmpEnableAuthenTraps));
snmp_enable_authen_traps(delete) ->
ok;
snmp_enable_authen_traps(get) ->
snmp_generic:variable_func(get, db(snmpEnableAuthenTraps)).
snmp_enable_authen_traps(set, NewVal) ->
snmp_generic:variable_func(set, NewVal, db(snmpEnableAuthenTraps)).
%%-----------------------------------------------------------------
%% This is the instrumentation function for sysObjectId
%%-----------------------------------------------------------------
sys_object_id(new) ->
snmp_generic:variable_func(new, db(sysObjectID));
sys_object_id(delete) ->
ok;
sys_object_id(get) ->
snmp_generic:variable_func(get, db(sysObjectID)).
sys_object_id(set, NewVal) ->
snmp_generic:variable_func(set, NewVal, db(sysObjectID)).
%%-----------------------------------------------------------------
%% This is a dummy instrumentation function for objects like
%% snmpTrapOID, that is accessible-for-notify, with different
%% values each time. This function will only be called with
%% new/delete.
%%-----------------------------------------------------------------
dummy(_Op) -> ok.
%%-----------------------------------------------------------------
%% This is the instrumentation function for snmpSetSerialNo.
%% It is always volatile.
%%-----------------------------------------------------------------
snmp_set_serial_no(new) ->
snmp_generic:variable_func(new, {snmpSetSerialNo, volatile}),
{A1,A2,A3} = erlang:now(),
random:seed(A1,A2,A3),
Val = random:uniform(2147483648) - 1,
snmp_generic:variable_func(set, Val, {snmpSetSerialNo, volatile});
snmp_set_serial_no(delete) ->
ok;
snmp_set_serial_no(get) ->
snmp_generic:variable_func(get, {snmpSetSerialNo, volatile}).
snmp_set_serial_no(is_set_ok, NewVal) ->
case snmp_generic:variable_func(get, {snmpSetSerialNo, volatile}) of
{value, NewVal} -> noError;
_ -> inconsistentValue
end;
snmp_set_serial_no(set, NewVal) ->
snmp_generic:variable_func(set, (NewVal + 1) rem 2147483648,
{snmpSetSerialNo, volatile}).
%%-----------------------------------------------------------------
%% This is the instrumentation function for sysOrTable
%%-----------------------------------------------------------------
sys_or_table(Op, RowIndex, Cols) ->
snmp_generic:table_func(Op, RowIndex, Cols, {sysORTable, volatile}).
add_agent_caps(Oid, Descr) when is_list(Oid) andalso is_list(Descr) ->
{value, Next} = snmpa_local_db:variable_get({next_sys_or_index, volatile}),
snmpa_local_db:variable_set({next_sys_or_index, volatile}, Next+1),
SysUpTime = sys_up_time(),
Row = {Next, Oid, Descr, SysUpTime},
snmpa_local_db:table_create_row({sysORTable, volatile}, [Next], Row),
snmpa_local_db:variable_set({sysORLastChange, volatile}, SysUpTime),
Next.
del_agent_caps(Index) ->
snmpa_local_db:table_delete_row({sysORTable, volatile}, [Index]),
snmpa_local_db:variable_set({sysORLastChange, volatile}, sys_up_time()).
get_agent_caps() ->
snmpa_local_db:match({sysORTable, volatile}, {'$1', '$2', '$3', '$4'}).
db(Var) -> snmpa_agent:db(Var).
%% -----
set_sname() ->
set_sname(get(sname)).
set_sname(undefined) ->
put(sname,conf);
set_sname(_) -> %% Keep it, if already set.
ok.
error(Reason) ->
throw({error, Reason}).
config_err(F, A) ->
snmpa_error:config_err("[STANDARD-MIB]: " ++ F, A).