aboutsummaryrefslogtreecommitdiffstats
path: root/lib/snmp/src/agent/snmp_framework_mib.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/snmp/src/agent/snmp_framework_mib.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/snmp/src/agent/snmp_framework_mib.erl')
-rw-r--r--lib/snmp/src/agent/snmp_framework_mib.erl440
1 files changed, 440 insertions, 0 deletions
diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl
new file mode 100644
index 0000000000..0916e2ec74
--- /dev/null
+++ b/lib/snmp/src/agent/snmp_framework_mib.erl
@@ -0,0 +1,440 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. 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_framework_mib).
+
+-include("snmp_types.hrl").
+-include("STANDARD-MIB.hrl").
+
+-define(VMODULE,"FRAMEWORK-MIB").
+-include("snmp_verbosity.hrl").
+
+-ifndef(default_verbosity).
+-define(default_verbosity,silence).
+-endif.
+
+
+%%%-----------------------------------------------------------------
+%%% This module implements the init- configure- and instrumentation-
+%%% functions for the SNMP-FRAMEWORK-MIB.
+%%%
+%%% We also keep internal datastructures here, e.g. a table
+%%% over all known contexts.
+%%%-----------------------------------------------------------------
+%% External exports
+-export([init/0, configure/1]).
+-export([intContextTable/1, intContextTable/3,
+ intAgentUDPPort/1, intAgentIpAddress/1,
+ snmpEngineID/1,
+ snmpEngineBoots/1,
+ snmpEngineTime/1,
+ snmpEngineMaxMessageSize/1,
+ get_engine_id/0, get_engine_max_message_size/0,
+ get_engine_boots/0, get_engine_time/0,
+ set_engine_boots/1, set_engine_time/1,
+ table_next/2, check_status/3]).
+-export([add_context/1, delete_context/1]).
+-export([check_agent/1, check_context/1]).
+
+
+%%-----------------------------------------------------------------
+%% Func: init/0
+%% Purpose: Creates the tables and variables necessary for the SNMP
+%% mechanism to work properly.
+%% Note that this function won't destroy any old values.
+%% This function should be called only once.
+%%-----------------------------------------------------------------
+init() ->
+ maybe_create_table(intContextTable),
+ init_engine().
+
+
+%%-----------------------------------------------------------------
+%% 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 internal tables, and
+%% inserts the data. Makes sure that all old data in
+%% the tables are deleted, and the new data inserted.
+%% This function makes sure that all (and only)
+%% config-file-data are in the tables.
+%% Returns: ok
+%% Fails: exit(configuration_error)
+%% PRE: init/1 has been successfully called
+%%-----------------------------------------------------------------
+configure(Dir) ->
+ set_sname(),
+ case snmpa_agent:get_agent_mib_storage() of
+ mnesia ->
+ ok;
+ _ ->
+ 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
+ end,
+ ok.
+
+do_configure(Dir) ->
+ ?vdebug("read internal config files",[]),
+ Contexts = read_internal_config_files(Dir),
+ ?vdebug("read agent config files",[]),
+ Agent = read_agent(Dir),
+ ?vdebug("initiate vars",[]),
+ init_vars(Agent),
+ %% Add default context, if not present.
+ NContexts = [{""} | lists:delete({""}, Contexts)],
+ ?vdebug("initiate tables",[]),
+ init_tabs(NContexts),
+ ok.
+
+read_internal_config_files(Dir) ->
+ ?vdebug("read context config file",[]),
+ Gen = fun(D) -> convert_context(D) end,
+ Filter = fun(Contexts) -> Contexts end,
+ Check = fun(Entry) -> check_context(Entry) end,
+ [Ctxs] = snmp_conf:read_files(Dir, [{Gen, Filter, Check, "context.conf"}]),
+ Ctxs.
+
+
+read_agent(Dir) ->
+ ?vdebug("read agent config file",[]),
+ Check = fun(Entry) -> check_agent(Entry) end,
+ File = filename:join(Dir, "agent.conf"),
+ Agent = snmp_conf:read(File, Check),
+ sort_agent(Agent).
+
+
+%%-----------------------------------------------------------------
+%% Make sure that each mandatory agent attribute is present, and
+%% provide default values for the other non-present attributes.
+%%-----------------------------------------------------------------
+sort_agent(L) ->
+ Mand = [{intAgentIpAddress, mandatory},
+ {intAgentUDPPort, mandatory},
+ {snmpEngineMaxMessageSize, mandatory},
+ {snmpEngineID, mandatory}],
+ {ok, L2} = snmp_conf:check_mandatory(L, Mand),
+ lists:keysort(1, L2).
+
+
+%%-----------------------------------------------------------------
+%% Generate a context.conf file.
+%%-----------------------------------------------------------------
+convert_context(Dir) ->
+ config_err("missing context.conf file => generating a default file", []),
+ File = filename:join(Dir,"context.conf"),
+ case file:open(File, [write]) of
+ {ok, Fid} ->
+ ok = io:format(Fid, "~s\n", [context_header()]),
+ ok = io:format(Fid, "%% The default context\n\"\".\n", []),
+ file:close(Fid);
+ {error, Reason} ->
+ file:delete(File),
+ error({failed_creating_file, File, Reason})
+ end.
+
+context_header() ->
+ {Y,Mo,D} = date(),
+ {H,Mi,S} = time(),
+ io_lib:format("%% This file was automatically generated by "
+ "snmp_config v~s ~w-~2.2.0w-~2.2.0w "
+ "~2.2.0w:~2.2.0w:~2.2.0w\n",
+ [?version,Y,Mo,D,H,Mi,S]).
+
+
+%%-----------------------------------------------------------------
+%% Context
+%% Context.
+%%-----------------------------------------------------------------
+check_context(Context) ->
+ ?vtrace("check_context -> entry with"
+ "~n Context: ~p", [Context]),
+ case (catch snmp_conf:check_string(Context)) of
+ ok ->
+ {ok, {Context}};
+ _ ->
+ error({invalid_context, Context})
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Agent
+%% {Name, Value}.
+%%-----------------------------------------------------------------
+check_agent({intAgentIpAddress, Value}) ->
+ snmp_conf:check_ip(Value);
+check_agent({intAgentUDPPort, Value}) ->
+ snmp_conf:check_integer(Value);
+%% This one is kept for backwards compatibility
+check_agent({intAgentMaxPacketSize, Value}) ->
+ snmp_conf:check_packet_size(Value);
+check_agent({snmpEngineMaxMessageSize, Value}) ->
+ snmp_conf:check_packet_size(Value);
+check_agent({snmpEngineID, Value}) ->
+ snmp_conf:check_string(Value);
+check_agent(X) ->
+ error({invalid_agent_attribute, X}).
+
+
+maybe_create_table(Name) ->
+ case snmpa_local_db:table_exists(db(Name)) of
+ true ->
+ ok;
+ _ ->
+ ?vtrace("create table: ~w",[Name]),
+ snmpa_local_db:table_create(db(Name))
+ end.
+
+init_vars(Vars) ->
+ lists:map(fun init_var/1, Vars).
+
+init_var({Var, Val}) ->
+ ?vtrace("init var: "
+ "~n set ~w to ~w",[Var, Val]),
+ snmp_generic:variable_set(db(Var), Val).
+
+init_tabs(Contexts) ->
+ ?vdebug("create context table",[]),
+ snmpa_local_db:table_delete(db(intContextTable)),
+ snmpa_local_db:table_create(db(intContextTable)),
+ init_context_table(Contexts).
+
+init_context_table([Row | T]) ->
+ Context = element(1, Row),
+ Key = [length(Context) | Context],
+ ?vtrace("create intContextTable table row for: ~w",[Key]),
+ snmpa_local_db:table_create_row(db(intContextTable), Key, Row),
+ init_context_table(T);
+init_context_table([]) -> true.
+
+
+table_cre_row(Tab, Key, Row) ->
+ snmpa_mib_lib:table_cre_row(db(Tab), Key, Row).
+
+table_del_row(Tab, Key) ->
+ snmpa_mib_lib:table_del_row(db(Tab), Key).
+
+
+%% FIXME: does not work with mnesia
+add_context(Ctx) ->
+ case (catch check_context(Ctx)) of
+ {ok, Row} ->
+ Context = element(1, Row),
+ Key = [length(Context) | Context],
+ case table_cre_row(intContextTable, Key, Row) of
+ true ->
+ {ok, Key};
+ false ->
+ {error, create_failed}
+ end;
+ {error, Reason} ->
+ {error, Reason};
+ Error ->
+ {error, Error}
+ end.
+
+%% FIXME: does not work with mnesia
+delete_context(Key) ->
+ case table_del_row(intContextTable, Key) of
+ true ->
+ ok;
+ false ->
+ {error, delete_failed}
+ end.
+
+
+%%-----------------------------------------------------------------
+%% Instrumentation functions
+%% Retreive functions are also used internally by the agent, so
+%% don't change the interface without changing those functions.
+%% Note that if these functions implementations are changed,
+%% an error can make the agent crash, as no error detection is
+%% performed for the internal data.
+%% These functions cannot use the default functions as is, because
+%% the default functions rely on that the mib is loaded, and
+%% these functions must work even if the OTP-FRAMEWORK-MIB isn't loaded.
+%% So we hardcode the information necessary for the functions
+%% called by the default functions in snmp_generic. This info is
+%% normally provided by the mib compiler, and inserted into
+%% snmpa_symbolic_store at load mib time.
+%%-----------------------------------------------------------------
+
+%%-----------------------------------------------------------------
+%% None if the int* objects are defined in any MIB.
+%%
+%% intContextTable keeps all
+%% known contexts internally, but is ordered as an SNMP table. It
+%% could be defined as:
+%% intContextTable OBJECT-TYPE
+%% SYNTAX SEQUENCE OF IntContextEntry
+%% MAX-ACCESS not-accessible
+%% STATUS current
+%% DESCRIPTION "A table of locally available contexts."
+%% ::= { xx }
+%%
+%% intContextEntry OBJECT-TYPE
+%% SYNTAX IntContextEntry
+%% MAX-ACCESS not-accessible
+%% STATUS current
+%% DESCRIPTION "Information about a particular context."
+%% INDEX {
+%% intContextName
+%% }
+%% ::= { intContextTable 1 }
+%%
+%% IntContextEntry ::= SEQUENCE
+%% {
+%% intContextName SnmpAdminString
+%% }
+%%
+%% intContextName OBJECT-TYPE
+%% SYNTAX SnmpAdminString (SIZE(0..32))
+%% MAX-ACCESS read-only
+%% STATUS current
+%% DESCRIPTION "A human readable name identifying a particular
+%% context at a particular SNMP entity.
+%%
+%% The empty contextName (zero length) represents the
+%% default context.
+%% "
+%% ::= { intContextEntry 1 }
+%%-----------------------------------------------------------------
+
+%% Op == new | delete
+intContextTable(Op) ->
+ snmp_generic:table_func(Op, db(intContextTable)).
+
+%% Op == get get_next -- READ only table
+intContextTable(get, RowIndex, Cols) ->
+ get(intContextTable, RowIndex, Cols);
+intContextTable(get_next, RowIndex, Cols) ->
+ next(intContextTable, RowIndex, Cols);
+intContextTable(Op, Arg1, Arg2) ->
+ snmp_generic:table_func(Op, Arg1, Arg2, db(intContextTable)).
+
+%% FIXME: exported, not used by agent, not documented - remove?
+table_next(Name, RestOid) ->
+ snmp_generic:table_next(db(Name), RestOid).
+
+%% FIXME: exported, not used by agent, not documented - remove?
+%% FIXME: does not work with mnesia
+check_status(Name, Indexes, StatusNo) ->
+ case snmpa_local_db:table_get_element(db(Name), Indexes, StatusNo) of
+ {value, ?'RowStatus_active'} -> true;
+ _ -> false
+ end.
+
+db(intContextTable) -> {intContextTable, volatile};
+db(X) -> snmpa_agent:db(X).
+
+fa(intContextTable) -> 1.
+
+foi(intContextTable) -> 1.
+
+noc(intContextTable) -> 1.
+
+next(Name, RowIndex, Cols) ->
+ snmp_generic:handle_table_next(db(Name), RowIndex, Cols,
+ fa(Name), foi(Name), noc(Name)).
+
+get(Name, RowIndex, Cols) ->
+ snmp_generic:handle_table_get(db(Name), RowIndex, Cols, foi(Name)).
+
+%% Op == new | delete | get
+intAgentUDPPort(Op) ->
+ snmp_generic:variable_func(Op, db(intAgentUDPPort)).
+
+intAgentIpAddress(Op) ->
+ snmp_generic:variable_func(Op, db(intAgentIpAddress)).
+
+snmpEngineID(Op) ->
+ snmp_generic:variable_func(Op, db(snmpEngineID)).
+
+snmpEngineMaxMessageSize(Op) ->
+ snmp_generic:variable_func(Op, db(snmpEngineMaxMessageSize)).
+
+snmpEngineBoots(Op) ->
+ snmp_generic:variable_func(Op, db(snmpEngineBoots)).
+
+snmpEngineTime(get) ->
+ {value, get_engine_time()}.
+
+init_engine() ->
+ case snmp_generic:variable_get(db(snmpEngineBoots)) of
+ {value, Val} when Val < 2147483647 ->
+ snmp_generic:variable_set(db(snmpEngineBoots), Val+1);
+ {value, _} ->
+ ok;
+ undefined ->
+ snmp_generic:variable_set(db(snmpEngineBoots), 1)
+ end,
+ reset_engine_base().
+
+
+reset_engine_base() ->
+ ets:insert(snmp_agent_table, {snmp_engine_base, snmp_misc:now(sec)}).
+
+get_engine_id() ->
+ {value, EngineID} = snmpEngineID(get),
+ EngineID.
+
+get_engine_max_message_size() ->
+ {value, MPS} = snmpEngineMaxMessageSize(get),
+ MPS.
+
+get_engine_time() ->
+ [{_, EngineBase}] = ets:lookup(snmp_agent_table, snmp_engine_base),
+ snmp_misc:now(sec) - EngineBase.
+
+get_engine_boots() ->
+ {value, Val} = snmpEngineBoots(get),
+ Val.
+
+set_engine_boots(Boots) ->
+ snmp_generic:variable_func(set, Boots, db(snmpEngineBoots)).
+
+set_engine_time(Time) ->
+ Base = snmp_misc:now(sec) - Time,
+ ets:insert(snmp_agent_table, {snmp_engine_base, Base}).
+
+
+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("[FRAMEWORK-MIB]: " ++ F, A).
+