diff options
Diffstat (limited to 'lib/snmp/src')
-rw-r--r-- | lib/snmp/src/agent/snmpa.erl | 17 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_agent.erl | 130 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_net_if.erl | 112 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_usm.erl | 18 | ||||
-rw-r--r-- | lib/snmp/src/app/snmp.appup.src | 52 | ||||
-rw-r--r-- | lib/snmp/src/manager/snmpm_config.erl | 62 | ||||
-rw-r--r-- | lib/snmp/src/manager/snmpm_net_if.erl | 66 | ||||
-rw-r--r-- | lib/snmp/src/misc/snmp_config.erl | 144 | ||||
-rw-r--r-- | lib/snmp/src/misc/snmp_log.erl | 495 | ||||
-rw-r--r-- | lib/snmp/src/misc/snmp_usm.erl | 26 |
10 files changed, 812 insertions, 310 deletions
diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl index 79493bd892..a113bba3a7 100644 --- a/lib/snmp/src/agent/snmpa.erl +++ b/lib/snmp/src/agent/snmpa.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-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(snmpa). @@ -83,6 +83,7 @@ %% Audit Trail Log functions -export([log_to_txt/2, log_to_txt/3, log_to_txt/4, log_to_txt/5, log_to_txt/6, log_to_txt/7, + log_info/0, change_log_size/1, get_log_type/0, get_log_type/1, change_log_type/1, change_log_type/2, @@ -535,6 +536,7 @@ get_agent_caps() -> %%%----------------------------------------------------------------- %%% Audit Trail Log functions %%%----------------------------------------------------------------- + log_to_txt(LogDir, Mibs) -> OutFile = "snmpa_log.txt", LogName = ?audit_trail_log_name, @@ -555,6 +557,11 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> snmp:log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop). +log_info() -> + LogName = ?audit_trail_log_name, + snmp_log:info(LogName). + + change_log_size(NewSize) -> LogName = ?audit_trail_log_name, % The old (agent) default snmp:change_log_size(LogName, NewSize). diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index 508a1da514..fb04fca632 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% +%% +%% 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(snmpa_agent). @@ -58,6 +58,7 @@ -export([get_log_type/1, set_log_type/2]). -export([get_request_limit/1, set_request_limit/2]). -export([invalidate_ca_cache/0]). +-export([increment_counter/3]). -export([restart_worker/1, restart_set_worker/1]). %% Internal exports @@ -259,6 +260,29 @@ update_mibs_cache_age(Agent, Age) -> call(Agent, {mibs_cache_request, {update_age, Age}}). +increment_counter(Counter, Initial, Max) -> + %% This is to make sure no one else increments our counter + Key = {Counter, self()}, + + %% Counter data + Position = 2, + Increment = 1, + Threshold = Max, + SetValue = Initial, + UpdateOp = {Position, Increment, Threshold, SetValue}, + + %% And now for the actual increment + Tab = snmp_agent_table, + case (catch ets:update_counter(Tab, Key, UpdateOp)) of + {'EXIT', {badarg, _}} -> + %% Oups, first time + ets:insert(Tab, {Key, Initial}), + Initial; + Next when is_integer(Next) -> + Next + end. + + init([Prio, Parent, Ref, Options]) -> ?d("init -> entry with" "~n Prio: ~p" @@ -1223,79 +1247,23 @@ handle_mibs_cache_request(MibServer, Req) -> %% Downgrade %% -code_change({down, _Vsn}, S, downgrade_to_pre_4_13) -> - S1 = workers_restart(S), - case S1#state.disco of - undefined -> - ok; - #disco{from = From, - sender = Sender, - stage = Stage} -> - gen_server:reply(From, {error, {upgrade, Stage, Sender}}), - exit(Sender, kill) - end, - S2 = {state, - S1#state.type, - S1#state.parent, - S1#state.worker, - S1#state.worker_state, - S1#state.set_worker, - S1#state.multi_threaded, - S1#state.ref, - S1#state.vsns, - S1#state.nfilters, - S1#state.note_store, - S1#state.mib_server, - S1#state.net_if, - S1#state.net_if_mod, - S1#state.backup, - S1#state.disco}, - {ok, S2}; +%% code_change({down, _Vsn}, S, downgrade_to_pre_4_13) -> +%% {ok, S2}; %% Upgrade %% -code_change(_Vsn, S, upgrade_from_pre_4_13) -> - {state, - Type, - Parent, - Worker, - WorkerState, - SetWorker, - MultiThreaded, - Ref, - Vsns, - NFilters = [], - NoteStore, - MibServer, %% Currently unused - NetIf, %% Currently unused - NetIfMod, - Backup} = S, - S1 = #state{type = Type, - parent = Parent, - worker = Worker, - worker_state = WorkerState, - set_worker = SetWorker, - multi_threaded = MultiThreaded, - ref = Ref, - vsns = Vsns, - nfilters = NFilters, - note_store = NoteStore, - mib_server = MibServer, - net_if = NetIf, - net_if_mod = NetIfMod, - backup = Backup}, - S2 = workers_restart(S1), - {ok, S2}; +%% code_change(_Vsn, S, upgrade_from_pre_4_13) -> +%% {ok, S2}; code_change(_Vsn, S, _Extra) -> {ok, S}. -workers_restart(#state{worker = W, set_worker = SW} = S) -> - Worker = worker_restart(W), - SetWorker = set_worker_restart(SW), - S#state{worker = Worker, - set_worker = SetWorker}. +%% workers_restart(#state{worker = W, set_worker = SW} = S) -> +%% Worker = worker_restart(W), +%% SetWorker = set_worker_restart(SW), +%% S#state{worker = Worker, +%% set_worker = SetWorker}. %%----------------------------------------------------------------- @@ -1321,8 +1289,8 @@ set_worker_start() -> worker_start(Dict) -> proc_lib:spawn_link(?MODULE, worker, [self(), Dict]). -worker_stop(Pid) -> - worker_stop(Pid, infinity). +%% worker_stop(Pid) -> +%% worker_stop(Pid, infinity). worker_stop(Pid, Timeout) when is_pid(Pid) -> Pid ! terminate, @@ -1336,17 +1304,17 @@ worker_stop(Pid, Timeout) when is_pid(Pid) -> worker_stop(_, _) -> ok. -set_worker_restart(Pid) -> - worker_restart(Pid, [{master, self()} | get()]). +%% set_worker_restart(Pid) -> +%% worker_restart(Pid, [{master, self()} | get()]). -worker_restart(Pid) -> - worker_restart(Pid, get()). +%% worker_restart(Pid) -> +%% worker_restart(Pid, get()). -worker_restart(Pid, Dict) when is_pid(Pid) -> - worker_stop(Pid), - worker_start(Dict); -worker_restart(Any, _Dict) -> - Any. +%% worker_restart(Pid, Dict) when is_pid(Pid) -> +%% worker_stop(Pid), +%% worker_start(Dict); +%% worker_restart(Any, _Dict) -> +%% Any. %%----------------------------------------------------------------- diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl index d703e5ac55..bc0777a7dd 100644 --- a/lib/snmp/src/agent/snmpa_net_if.erl +++ b/lib/snmp/src/agent/snmpa_net_if.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-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(snmpa_net_if). @@ -55,6 +55,9 @@ -define(DEFAULT_FILTER_MODULE, snmpa_net_if_filter). -define(DEFAULT_FILTER_OPTS, [{module, ?DEFAULT_FILTER_MODULE}]). +-define(ATL_SEQNO_INITIAL, 1). +-define(ATL_SEQNO_MAX, 2147483647). + %%%----------------------------------------------------------------- %%% This module implements the default Network Interface part @@ -194,24 +197,43 @@ do_init(Prio, NoteStore, MasterAgent, Parent, Opts) -> {error, {udp_open, UDPPort, Reason}} end. + create_log() -> case ets:lookup(snmp_agent_table, audit_trail_log) of [] -> {undefined, []}; [{audit_trail_log, AtlOpts}] -> - ?vtrace("AtlOpts: ~p",[AtlOpts]), + ?vtrace("AtlOpts: ~p", [AtlOpts]), Type = get_atl_type(AtlOpts), Dir = get_atl_dir(AtlOpts), Size = get_atl_size(AtlOpts), Repair = get_atl_repair(AtlOpts), Name = ?audit_trail_log_name, File = filename:absname(?audit_trail_log_file, Dir), - case snmp_log:create(Name, File, Size, Repair, true) of - {ok, Log} -> - ?vdebug("log created: ~w",[Log]), - {Log, Type}; - {error, Reason} -> - throw({error, {create_log, Reason}}) + case get_atl_seqno(AtlOpts) of + true -> + Initial = ?ATL_SEQNO_INITIAL, + Max = ?ATL_SEQNO_MAX, + Module = snmpa_agent, + Function = increment_counter, + Args = [atl_seqno, Initial, Max], + SeqNoGen = {Module, Function, Args}, + case snmp_log:create(Name, File, + SeqNoGen, Size, Repair, true) of + {ok, Log} -> + ?vdebug("log created: ~w", [Log]), + {Log, Type}; + {error, Reason} -> + throw({error, {create_log, Reason}}) + end; + _ -> + case snmp_log:create(Name, File, Size, Repair, true) of + {ok, Log} -> + ?vdebug("log created: ~w", [Log]), + {Log, Type}; + {error, Reason} -> + throw({error, {create_log, Reason}}) + end end end. @@ -918,60 +940,23 @@ system_continue(_Parent, _Dbg, S) -> loop(S). system_terminate(Reason, _Parent, _Dbg, #state{log = Log}) -> + ?vlog("system-terminate -> entry with" + "~n Reason: ~p", [Reason]), do_close_log(Log), exit(Reason). -system_code_change(OldState, _Module, _OldVsn, upgrade_from_pre_4_10) -> - {state, - parent = Parent, - note_store = NS, - master_agent = MA, - usock = Sock, - usock_opts = SockOpts, - mpd_state = MpdState, - log = Log, - reqs = Reqs, - debug = Dbg, - limit = Limit, - rcnt = RCNT} = OldState, - NewState = #state{parent = Parent, - note_store = NS, - master_agent = MA, - usock = Sock, - usock_opts = SockOpts, - mpd_state = MpdState, - log = Log, - reqs = Reqs, - debug = Dbg, - limit = Limit, - rcnt = RCNT, - filter = create_filter(?DEFAULT_FILTER_OPTS)}, +system_code_change(OldState, _Module, _OldVsn, upgrade_from_pre_4_16) -> + Initial = ?ATL_SEQNO_INITIAL, + Max = ?ATL_SEQNO_MAX, + Module = snmpa_agent, + Function = increment_counter, + Args = [atl_seqno, Initial, Max], + SeqNoGen = {Module, Function, Args}, + NewLog = snmp_log:upgrade(OldState#state.log, SeqNoGen), + NewState = OldState#state{log = NewLog}, {ok, NewState}; -system_code_change(OldState, _Module, _OldVsn, downgrade_to_pre_4_10) -> - #state{parent = Parent, - note_store = NS, - master_agent = MA, - usock = Sock, - usock_opts = SockOpts, - mpd_state = MpdState, - log = Log, - reqs = Reqs, - debug = Dbg, - limit = Limit, - rcnt = RCNT} = OldState, - NewState = - {state, - parent = Parent, - note_store = NS, - master_agent = MA, - usock = Sock, - usock_opts = SockOpts, - mpd_state = MpdState, - log = Log, - reqs = Reqs, - debug = Dbg, - limit = Limit, - rcnt = RCNT}, +system_code_change(OldState, _Module, _OldVsn, downgrade_to_pre_4_16) -> + NewState = OldState#state{log = snmp_log:downgrade(OldState#state.log)}, {ok, NewState}; system_code_change(S, _Module, _OldVsn, _Extra) -> {ok, S}. @@ -1111,6 +1096,9 @@ get_atl_size(Opts) -> get_atl_repair(Opts) -> snmp_misc:get_option(repair, Opts, true). +get_atl_seqno(Opts) -> + snmp_misc:get_option(seqno, Opts, false). + get_verbosity(Opts) -> snmp_misc:get_option(verbosity, Opts, ?default_verbosity). diff --git a/lib/snmp/src/agent/snmpa_usm.erl b/lib/snmp/src/agent/snmpa_usm.erl index a8c395534f..12a6b996ff 100644 --- a/lib/snmp/src/agent/snmpa_usm.erl +++ b/lib/snmp/src/agent/snmpa_usm.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1999-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(snmpa_usm). @@ -396,7 +396,9 @@ try_decrypt(?usmDESPrivProtocol, case (catch des_decrypt(PrivKey, UsmSecParams, EncryptedPDU)) of {ok, DecryptedData} -> DecryptedData; - _ -> + Error -> + ?vlog("try_decrypt -> failed DES decrypt" + "~n Error: ~p", [Error]), error(usmStatsDecryptionErrors, ?usmStatsDecryptionErrors_instance, % OTP-5464 SecName) @@ -406,7 +408,9 @@ try_decrypt(?usmAesCfb128Protocol, case (catch aes_decrypt(PrivKey, UsmSecParams, EncryptedPDU)) of {ok, DecryptedData} -> DecryptedData; - _ -> + Error -> + ?vlog("try_decrypt -> failed AES decrypt" + "~n Error: ~p", [Error]), error(usmStatsDecryptionErrors, ?usmStatsDecryptionErrors_instance, % OTP-5464 SecName) diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 0b8f0bbddd..74747b2e59 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1999-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% %% @@ -24,10 +24,21 @@ [ {"4.15", [ + {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16}, + soft_purge, soft_purge, [snmpa_agent, snmp_log]}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.14", [ + {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16}, + soft_purge, soft_purge, [snmpa_agent, snmp_log]}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpm_user, soft_purge, soft_purge, []}, {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {update, snmpm_server, soft, soft_purge, soft_purge, @@ -36,11 +47,15 @@ }, {"4.13.5", [ - {load_module, snmpm_user, soft_purge, soft_purge, []}, - {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {load_module, snmpa_mib_data, soft_purge, soft_purge, []}, + {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16}, + soft_purge, soft_purge, [snmpa_agent, snmp_log]}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, - {update, snmpa_net_if, soft, soft_purge, soft_purge, []}, + + {load_module, snmpm_user, soft_purge, soft_purge, []}, + {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {update, snmpm_config, soft, soft_purge, soft_purge, []}, {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_user_default]}, {add_module, snmpm_net_if_filter}, @@ -54,10 +69,21 @@ [ {"4.15", [ + {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16}, + soft_purge, soft_purge, [snmpa_agent, snmp_log]}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.14", [ + {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16}, + soft_purge, soft_purge, [snmpa_agent, snmp_log]}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpm_user, soft_purge, soft_purge, []}, {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_user_default]} @@ -65,11 +91,15 @@ }, {"4.13.5", [ - {load_module, snmpm_user, soft_purge, soft_purge, []}, - {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {load_module, snmpa_mib_data, soft_purge, soft_purge, []}, + {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16}, + soft_purge, soft_purge, [snmpa_agent, snmp_log]}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, - {update, snmpa_net_if, soft, soft_purge, soft_purge, []}, + + {load_module, snmpm_user, soft_purge, soft_purge, []}, + {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {update, snmpm_config, soft, soft_purge, soft_purge, []}, {update, snmpm_server, soft, soft_purge, soft_purge, [snmpm_user_default]}, {remove, {snmpm_net_if_filter, soft_purge, brutal_purge}}, diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 1a5400bf8e..e4069485ad 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-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% %% %% ------------------------------------------------------------------------- @@ -63,6 +63,7 @@ cre_counter/2, incr_counter/2, + increment_counter/3, increment_counter/4, cre_stats_counter/2, maybe_cre_stats_counter/2, @@ -792,6 +793,34 @@ incr_counter(Counter, Incr, Wrap) -> end. +%% <ATL Sequence Number> +increment_counter(Counter, Initial, Max) -> + Increment = 1, + increment_counter(Counter, Initial, Increment, Max). + +increment_counter(Counter, Initial, Increment, Max) -> + %% This is to make sure no one else increments our counter + Key = {Counter, self()}, + + %% Counter data + Position = 2, + Threshold = Max, + SetValue = Initial, + UpdateOp = {Position, Increment, Threshold, SetValue}, + + %% And now for the actual increment + Tab = snmpm_counter_table, + case (catch ets:update_counter(Tab, Key, UpdateOp)) of + {'EXIT', {badarg, _}} -> + %% Oups, first time + ets:insert(Tab, {Key, Initial}), + Initial; + Next when is_integer(Next) -> + Next + end. +%% </ATL Sequence Number> + + maybe_cre_stats_counter(Counter, Initial) -> case ets:lookup(snmpm_stats_table, Counter) of [_] -> @@ -1013,14 +1042,16 @@ do_init(Opts) -> AuditTrailLogOpts -> ?vtrace("ATL options: ~p", [AuditTrailLogOpts]), ets:insert(snmpm_config_table, {audit_trail_log, true}), - LogDir = get_atl_dir(AuditTrailLogOpts), - LogType = get_atl_type(AuditTrailLogOpts), - LogSize = get_atl_size(AuditTrailLogOpts), - LogRep = get_atl_repair(AuditTrailLogOpts), + LogDir = get_atl_dir(AuditTrailLogOpts), + LogType = get_atl_type(AuditTrailLogOpts), + LogSize = get_atl_size(AuditTrailLogOpts), + LogRep = get_atl_repair(AuditTrailLogOpts), + LogSeqNo = get_atl_seqno(AuditTrailLogOpts), ets:insert(snmpm_config_table, {audit_trail_log_dir, LogDir}), ets:insert(snmpm_config_table, {audit_trail_log_type, LogType}), ets:insert(snmpm_config_table, {audit_trail_log_size, LogSize}), - ets:insert(snmpm_config_table, {audit_trail_log_repair, LogRep}) + ets:insert(snmpm_config_table, {audit_trail_log_repair, LogRep}), + ets:insert(snmpm_config_table, {audit_trail_log_seqno, LogSeqNo}) end, %% -- System default agent config -- @@ -1398,6 +1429,9 @@ verify_audit_trail_log_opts([{size, Size}|Opts]) -> verify_audit_trail_log_opts([{repair, Repair}|Opts]) -> verify_log_repair(Repair), verify_audit_trail_log_opts(Opts); +verify_audit_trail_log_opts([{seqno, SeqNo}|Opts]) -> + verify_log_seqno(SeqNo), + verify_audit_trail_log_opts(Opts); verify_audit_trail_log_opts([Opt|_Opts]) -> error({invalid_audit_trail_log_option, Opt}). @@ -1440,6 +1474,11 @@ verify_log_repair(truncate) -> ok; verify_log_repair(Repair) -> error({invalid_audit_trail_log_repair, Repair}). +verify_log_seqno(true) -> ok; +verify_log_seqno(false) -> ok; +verify_log_seqno(SeqNo) -> + error({invalid_audit_trail_log_seqno, SeqNo}). + verify_module(_, Mod) when is_atom(Mod) -> ok; @@ -3040,6 +3079,9 @@ get_atl_size(Opts) -> get_atl_repair(Opts) -> get_opt(repair, Opts, truncate). +get_atl_seqno(Opts) -> + get_opt(seqno, Opts, false). + %%---------------------------------------------------------------------- diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl index 14d39933dc..4ec24af7f3 100644 --- a/lib/snmp/src/manager/snmpm_net_if.erl +++ b/lib/snmp/src/manager/snmpm_net_if.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-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% %% @@ -81,6 +81,9 @@ -define(IRGC_TIMEOUT, timer:minutes(5)). +-define(ATL_SEQNO_INITIAL, 1). +-define(ATL_SEQNO_MAX, 2147483647). + %%%------------------------------------------------------------------- %%% API @@ -297,11 +300,29 @@ do_init_log(true) -> {ok, Repair} = snmpm_config:system_info(audit_trail_log_repair), Name = ?audit_trail_log_name, File = filename:absname(?audit_trail_log_file, Dir), - case snmp_log:create(Name, File, Size, Repair, true) of - {ok, Log} -> - {Log, Type}; - {error, Reason} -> - throw({error, {failed_create_audit_log, Reason}}) + case snmpm_config:system_info(audit_trail_log_seqno) of + {ok, true} -> + Initial = ?ATL_SEQNO_INITIAL, + Max = ?ATL_SEQNO_MAX, + Module = snmpm_config, + Function = increment_counter, + Args = [atl_seqno, Initial, Max], + SeqNoGen = {Module, Function, Args}, + case snmp_log:create(Name, File, + SeqNoGen, Size, Repair, true) of + {ok, Log} -> + ?vdebug("log created: ~w", [Log]), + {Log, Type}; + {error, Reason} -> + throw({error, {failed_create_audit_log, Reason}}) + end; + _ -> + case snmp_log:create(Name, File, Size, Repair, true) of + {ok, Log} -> + {Log, Type}; + {error, Reason} -> + throw({error, {failed_create_audit_log, Reason}}) + end end. @@ -441,32 +462,15 @@ do_close_log(_) -> %% Returns: {ok, NewState} %%---------------------------------------------------------------------- -code_change({down, _Vsn}, OldState, downgrade_to_pre45) -> +code_change({down, _Vsn}, OldState, downgrade_to_pre_4_16) -> ?d("code_change(down) -> entry", []), - #state{server = Server, - note_store = NoteStore, - sock = Sock, - mpd_state = MpdState, - log = Log, - irgc = IrGcRef} = OldState, - irgc_stop(IrGcRef), - (catch ets:delete(snmpm_inform_request_table)), - State = {state, Server, NoteStore, Sock, MpdState, Log}, + State = OldState#state{log = snmp_log:downgrade(OldState#state.log)}, {ok, State}; % upgrade -code_change(_Vsn, OldState, upgrade_from_pre45) -> +code_change(_Vsn, OldState, upgrade_from_pre_4_16) -> ?d("code_change(up) -> entry", []), - {state, Server, NoteStore, Sock, MpdState, Log} = OldState, - State = #state{server = Server, - note_store = NoteStore, - sock = Sock, - mpd_state = MpdState, - log = Log, - irb = auto, - irgc = undefined}, - ets:new(snmpm_inform_request_table, - [set, protected, named_table, {keypos, 1}]), + State = OldState#state{log = snmp_log:upgrade(OldState#state.log)}, {ok, State}; code_change(_Vsn, State, _Extra) -> diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl index ad41eaf160..0ee373a4d4 100644 --- a/lib/snmp/src/misc/snmp_config.erl +++ b/lib/snmp/src/misc/snmp_config.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% +%% +%% 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% %% @@ -327,10 +327,15 @@ config_agent_sys() -> ATLRepair = ask("23f. Audit trail log repair " "(true/false/truncate/snmp_repair)?", "true", fun verify_atl_repair/1), + ATLSeqNo = ask("23g. Audit trail log " + "sequence-numbering (true/false)?", + "false", + fun verify_atl_seqno/1), [{audit_trail_log, [{type, ATLType}, {dir, ATLDir}, {size, ATLSize}, - {repair, ATLRepair}]}]; + {repair, ATLRepair}, + {seqno, ATLSeqNo}]}]; no -> [] end, @@ -400,8 +405,39 @@ config_agent_sys() -> NetIf = [{module, NetIfMod}, {verbosity, NetIfVerb}, {options, NetIfOpts}], + TermDiscoEnable = ask("26a. Allow terminating discovery " + "(true/false)?", "true", + fun verify_bool/1), + TermDiscoConf = + case TermDiscoEnable of + true -> + TermDiscoStage2 = + ask("26b. Second stage behaviour " + "(discovery/plain)?", "discovery", + fun verify_term_disco_behaviour/1), + TermDiscoTrigger = + ask("26c. Trigger username " + "(default/a string)?", "default", + fun verify_term_disco_trigger_username/1), + [{enable, TermDiscoEnable}, + {stage2, TermDiscoStage2}, + {trigger_username, TermDiscoTrigger}]; + false -> + [{enable, TermDiscoEnable}, + {stage2, discovery}, + {trigger_username, ""}] + end, + OrigDiscoEnable = ask("27a. Allow originating discovery " + "(true/false)?", "true", + fun verify_bool/1), + OrigDiscoConf = + [{enable, OrigDiscoEnable}], + DiscoveryConfig = + [{terminating, TermDiscoConf}, + {originating, OrigDiscoConf}], [{agent_type, master}, {agent_verbosity, MasterAgentVerb}, + {discovery, DiscoveryConfig}, {config, [{dir, ConfigDir}, {force_load, ForceLoad}, {verbosity, ConfigVerb}]}, @@ -644,23 +680,31 @@ config_manager_sys() -> "(y/n)?", "n", fun verify_yes_or_no/1) of yes -> - ATLDir = ask("19b. Where to store the " + ATLType = ask("19b. Audit trail log type " + "(write/read_write)?", + "read_write", fun verify_atl_type/1), + ATLDir = ask("19c. Where to store the " "audit trail log?", DefDir, fun verify_dir/1), - ATLMaxFiles = ask("19c. Max number of files?", + ATLMaxFiles = ask("19d. Max number of files?", "10", fun verify_pos_integer/1), - ATLMaxBytes = ask("19d. Max size (in bytes) " + ATLMaxBytes = ask("19e. Max size (in bytes) " "of each file?", "10240", fun verify_pos_integer/1), ATLSize = {ATLMaxBytes, ATLMaxFiles}, - ATLRepair = ask("19e. Audit trail log repair " + ATLRepair = ask("19f. Audit trail log repair " "(true/false/truncate/snmp_repair)?", "true", fun verify_atl_repair/1), - [{audit_trail_log, [{dir, ATLDir}, + ATLSeqNo = ask("19g. Audit trail log sequence-numbering " + "(true/false)?", "false", + fun verify_atl_seqno/1), + [{audit_trail_log, [{type, ATLType}, + {dir, ATLDir}, {size, ATLSize}, - {repair, ATLRepair}]}]; + {repair, ATLRepair}, + {seqno, ATLSeqNo}]}]; no -> [] end, @@ -1180,6 +1224,13 @@ verify_atl_repair("snmp_repair") -> verify_atl_repair(R) -> {error, "invalid audit trail log repair: " ++ R}. +verify_atl_seqno("true") -> + {ok, true}; +verify_atl_seqno("false") -> + {ok, false}; +verify_atl_seqno(SN) -> + {error, "invalid audit trail log seqno: " ++ SN}. + verify_pos_integer(I0) -> case (catch list_to_integer(I0)) of @@ -1237,6 +1288,18 @@ verify_irb_user(TO) -> end. +verify_term_disco_behaviour("discovery") -> + {ok, discovery}; +verify_term_disco_behaviour("plain") -> + {ok, plain}; +verify_term_disco_behaviour(B) -> + {error, "invalid terminating discovery behaviour: " ++ B}. + +verify_term_disco_trigger_username("default") -> + {ok, ""}; +verify_term_disco_trigger_username(Trigger) -> + {ok, Trigger}. + verify_user_id(UserId) when is_list(UserId) -> case (catch list_to_atom(UserId)) of @@ -2096,6 +2159,10 @@ write_sys_config_file_agent_opt(Fid, {audit_trail_log, Opts}) -> ok = io:format(Fid, " {audit_trail_log, [", []), write_sys_config_file_agent_atl_opts(Fid, Opts), ok = io:format(Fid, "}", []); +write_sys_config_file_agent_opt(Fid, {discovery, Opts}) -> + ok = io:format(Fid, " {discovery, [", []), + write_sys_config_file_agent_disco_opts(Fid, Opts), + ok = io:format(Fid, "}", []); write_sys_config_file_agent_opt(Fid, {net_if, Opts}) -> ok = io:format(Fid, " {net_if, ~w}", [Opts]); write_sys_config_file_agent_opt(Fid, {mib_server, Opts}) -> @@ -2139,7 +2206,58 @@ write_sys_config_file_agent_atl_opt(Fid, {type, Type}) -> write_sys_config_file_agent_atl_opt(Fid, {size, Size}) -> ok = io:format(Fid, "{size, ~w}", [Size]); write_sys_config_file_agent_atl_opt(Fid, {repair, Rep}) -> - ok = io:format(Fid, "{repair, ~w}", [Rep]). + ok = io:format(Fid, "{repair, ~w}", [Rep]); +write_sys_config_file_agent_atl_opt(Fid, {seqno, SeqNo}) -> + ok = io:format(Fid, "{seqno, ~w}", [SeqNo]). + + +%% These options are allways there +write_sys_config_file_agent_disco_opts(Fid, [Opt]) -> + write_sys_config_file_agent_disco_opt(Fid, Opt), + ok = io:format(Fid, "]", []), + ok; +write_sys_config_file_agent_disco_opts(Fid, [Opt|Opts]) -> + write_sys_config_file_agent_disco_opt(Fid, Opt), + ok = io:format(Fid, ", ", []), + write_sys_config_file_agent_disco_opts(Fid, Opts). + +write_sys_config_file_agent_disco_opt(Fid, {terminating, Opts}) -> + ok = io:format(Fid, "{terminating, [", []), + write_sys_config_file_agent_term_disco_opts(Fid, Opts), + ok = io:format(Fid, "}", []); +write_sys_config_file_agent_disco_opt(Fid, {originating, Opts}) -> + ok = io:format(Fid, "{originating, [", []), + write_sys_config_file_agent_orig_disco_opts(Fid, Opts), + ok = io:format(Fid, "}", []). + +write_sys_config_file_agent_term_disco_opts(Fid, [Opt]) -> + write_sys_config_file_agent_term_disco_opt(Fid, Opt), + ok = io:format(Fid, "]", []), + ok; +write_sys_config_file_agent_term_disco_opts(Fid, [Opt|Opts]) -> + write_sys_config_file_agent_term_disco_opt(Fid, Opt), + ok = io:format(Fid, ", ", []), + write_sys_config_file_agent_term_disco_opts(Fid, Opts). + +write_sys_config_file_agent_term_disco_opt(Fid, {enable, Enable}) -> + ok = io:format(Fid, "{enable, ~w}", [Enable]); +write_sys_config_file_agent_term_disco_opt(Fid, {stage2, Stage2}) -> + ok = io:format(Fid, "{stage2, ~w}", [Stage2]); +write_sys_config_file_agent_term_disco_opt(Fid, {trigger_username, Trigger}) -> + ok = io:format(Fid, "{trigger_username, \"~s\"}", [Trigger]). + +write_sys_config_file_agent_orig_disco_opts(Fid, [Opt]) -> + write_sys_config_file_agent_orig_disco_opt(Fid, Opt), + ok = io:format(Fid, "]", []), + ok; +write_sys_config_file_agent_orig_disco_opts(Fid, [Opt|Opts]) -> + write_sys_config_file_agent_orig_disco_opt(Fid, Opt), + ok = io:format(Fid, ", ", []), + write_sys_config_file_agent_orig_disco_opts(Fid, Opts). + +write_sys_config_file_agent_orig_disco_opt(Fid, {enable, Enable}) -> + ok = io:format(Fid, "{enable, ~w}", [Enable]). + write_sys_config_file_manager_opts(Fid, [Opt]) -> diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl index c3932ccc08..9f4fdf97ca 100644 --- a/lib/snmp/src/misc/snmp_log.erl +++ b/lib/snmp/src/misc/snmp_log.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-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% %% @@ -21,12 +21,19 @@ -export([ - create/4, create/5, + create/4, create/5, create/6, change_size/2, close/1, sync/1, info/1, log/4, log_to_txt/5, log_to_txt/6, log_to_txt/7, log_to_io/4, log_to_io/5, log_to_io/6 ]). +-export([ + upgrade/1, upgrade/2, + downgrade/1 + ]). +-export([ + validate/1, validate/2 + ]). -define(SNMP_USE_V3, true). @@ -38,30 +45,74 @@ -define(LOG_FORMAT, internal). -define(LOG_TYPE, wrap). +-record(snmp_log, {id, seqno}). + %% -------------------------------------------------------------------- %% Exported functions %% -------------------------------------------------------------------- +upgrade(Log) when is_record(Log, snmp_log) -> + Log; +upgrade(Log) -> + upgrade(Log, disabled). + +upgrade(Log, _SeqNoGen) when is_record(Log, snmp_log) -> + Log; +upgrade(Log, {M, F, A} = SeqNoGen) + when (is_atom(M) andalso is_atom(F) andalso is_list(A)) -> + #snmp_log{id = Log, seqno = SeqNoGen}; +upgrade(Log, SeqNoGen) + when is_function(SeqNoGen, 0) -> + #snmp_log{id = Log, seqno = SeqNoGen}; +upgrade(Log, disabled = SeqNoGen) -> + #snmp_log{id = Log, seqno = SeqNoGen}. + +downgrade(#snmp_log{id = Log}) -> + Log; +downgrade(Log) -> + Log. + %% -- create --- create(Name, File, Size, Repair) -> - create(Name, File, Size, Repair, false). - -create(Name, File, Size, Repair, Notify) -> + create(Name, File, disabled, Size, Repair, false). + +create(Name, File, Size, Repair, Notify) + when (((Repair =:= true) orelse + (Repair =:= false) orelse + (Repair =:= truncate) orelse + (Repair =:= snmp_repair)) andalso + ((Notify =:= true) orelse + (Notify =:= false))) -> + create(Name, File, disabled, Size, Repair, Notify); +create(Name, File, SeqNoGen, Size, Repair) -> + create(Name, File, SeqNoGen, Size, Repair, false). + +create(Name, File, SeqNoGen, Size, Repair, Notify) + when (((Repair =:= true) orelse + (Repair =:= false) orelse + (Repair =:= truncate) orelse + (Repair =:= snmp_repair)) andalso + ((Notify =:= true) orelse + (Notify =:= false))) -> ?vtrace("create -> entry with" - "~n Name: ~p" - "~n File: ~p" - "~n Size: ~p" - "~n Repair: ~p" - "~n Notify: ~p", [Name, File, Size, Repair, Notify]), - log_open(Name, File, Size, Repair, Notify). + "~n Name: ~p" + "~n File: ~p" + "~n SeqNoGen: ~p" + "~n Size: ~p" + "~n Repair: ~p" + "~n Notify: ~p", [Name, File, SeqNoGen, Size, Repair, Notify]), + log_open(Name, File, SeqNoGen, Size, Repair, Notify); +create(Name, File, SeqNoGen, Size, Repair, Notify) -> + {error, {bad_args, Name, File, SeqNoGen, Size, Repair, Notify}}. + %% -- close --- -close(Log) -> +close(#snmp_log{id = Log}) -> ?vtrace("close -> entry with" "~n Log: ~p", [Log]), disk_log:close(Log). @@ -69,14 +120,25 @@ close(Log) -> %% -- close --- +sync(#snmp_log{id = Log}) -> + do_sync(Log); sync(Log) -> + do_sync(Log). + +do_sync(Log) -> ?vtrace("sync -> entry with" "~n Log: ~p", [Log]), disk_log:sync(Log). + %% -- info --- +info(#snmp_log{id = Log}) -> + do_info(Log); info(Log) -> + do_info(Log). + +do_info(Log) -> case disk_log:info(Log) of Info when is_list(Info) -> Items = [no_current_bytes, no_current_items, @@ -97,6 +159,138 @@ info_filter([Item|Items], Info, Acc) -> end. +%% -- validate -- + +%% This function is used to "validate" a log. +%% At present this means making sure all entries +%% are in the proper order, and if sequence numbering +%% is used that no entries are missing. +%% It is intended to be used for testing. + +validate(Log) -> + validate(Log, false). + +validate(#snmp_log{id = Log}, SeqNoReq) -> + validate(Log, SeqNoReq); +validate(Log, SeqNoReq) + when ((SeqNoReq =:= true) orelse (SeqNoReq =:= false)) -> + Validator = + fun({Timestamp, SeqNo, _Packet, _Addr, _Port}, {PrevTS, PrevSN}) -> + ?vtrace("validating log entry when" + "~n Timestamp: ~p" + "~n SeqNo: ~p" + "~n PrevTS: ~p" + "~n PrevSN: ~p", + [Timestamp, SeqNo, PrevTS, PrevSN]), + validate_timestamp(PrevTS, Timestamp), + validate_seqno(PrevSN, SeqNo), + {Timestamp, SeqNo}; + + ({Timestamp, _Packet, _Addr, _Port}, {PrevTS, _PrevSN}) when SeqNoReq =:= true -> + ?vtrace("validating log entry when" + "~n Timestamp: ~p" + "~n PrevTS: ~p", + [Timestamp, PrevTS]), + throw({error, {missing_seqno, Timestamp}}); + + ({Timestamp, _Packet, _Addr, _Port}, {PrevTS, PrevSN}) -> + ?vtrace("validating log entry when" + "~n Timestamp: ~p" + "~n PrevTS: ~p", + [Timestamp, PrevTS]), + validate_timestamp(PrevTS, Timestamp), + {Timestamp, PrevSN}; + + (E, Acc) -> + ?vtrace("validating bad log entry when" + "~n E: ~p" + "~n Acc: ~p", + [E, Acc]), + throw({error, {bad_entry, E, Acc}}) + end, + try + begin + validate_loop(disk_log:chunk(Log, start), + Log, Validator, first, first) + end + catch + throw:Error -> + Error + end. + +%% We shall check that TS2 >= TS1 +validate_timestamp(first, _TS2) -> + ok; +validate_timestamp({LT1, UT1} = TS1, {LT2, UT2} = TS2) -> + LT1_Secs = calendar:datetime_to_gregorian_seconds(LT1), + UT1_Secs = calendar:datetime_to_gregorian_seconds(UT1), + LT2_Secs = calendar:datetime_to_gregorian_seconds(LT2), + UT2_Secs = calendar:datetime_to_gregorian_seconds(UT2), + case ((LT2_Secs >= LT1_Secs) andalso (UT2_Secs >= UT1_Secs)) of + true -> + ok; + false -> + throw({error, {invalid_timestamp, TS1, TS2}}) + end; +validate_timestamp(TS1, TS2) -> + throw({error, {bad_timestamp, TS1, TS2}}). + + +%% The usual case when SN2 = SN1 + 1 +validate_seqno(first, SN2) + when is_integer(SN2) >= 1 -> + ok; + +%% The usual case when SN2 = SN1 + 1 +validate_seqno(SN1, SN2) + when is_integer(SN1) andalso is_integer(SN2) andalso + (SN2 =:= (SN1 + 1)) andalso (SN1 >= 1) -> + ok; + +%% The case when we have a wrap +validate_seqno(SN1, SN2) + when is_integer(SN1) andalso is_integer(SN2) andalso + (SN2 < SN1) andalso (SN2 >= 1) -> + ok; + +%% And everything else must be an error... +validate_seqno(SN1, SN2) -> + throw({error, {bad_seqno, SN1, SN2}}). + +validate_loop(eof, _Log, _Validatior, _PrevTS, _PrevSN) -> + ok; +validate_loop({error, _} = Error, _Log, _Validator, _PrevTS, _PrevSN) -> + Error; +validate_loop({corrupt_log_file, _} = Reason, + _Log, _Validator, _PrevTS, _PrevSN) -> + {error, Reason}; +validate_loop({Cont, Terms}, Log, Validator, PrevTS, PrevSN) -> + ?vtrace("validate_loop -> entry with" + "~n Terms: ~p" + "~n PrevTS: ~p" + "~n PrevSN: ~p", [Terms, PrevTS, PrevSN]), + {NextTS, NextSN} = lists:foldl(Validator, {PrevTS, PrevSN}, Terms), + ?vtrace("validate_loop -> " + "~n NextTS: ~p" + "~n NextSN: ~p", [NextTS, NextSN]), + validate_loop(disk_log:chunk(Log, Cont), Log, Validator, NextTS, NextSN); +validate_loop({Cont, Terms, BadBytes}, Log, Validator, PrevTS, PrevSN) -> + ?vtrace("validate_loop -> entry with" + "~n Terms: ~p" + "~n BadBytes: ~p" + "~n PrevTS: ~p" + "~n PrevSN: ~p", [Terms, BadBytes, PrevTS, PrevSN]), + error_logger:error_msg("Skipping ~w bytes while validating ~p~n~n", + [BadBytes, Log]), + {NextTS, NextSN} = lists:foldl(Validator, {PrevTS, PrevSN}, Terms), + ?vtrace("validate_loop -> " + "~n NextTS: ~p" + "~n NextSN: ~p", [NextTS, NextSN]), + validate_loop(disk_log:chunk(Log, Cont), Log, Validator, NextTS, NextSN); +validate_loop(Error, _Log, _Write, _PrevTS, _PrevSN) -> + Error. + + %% -- log --- %%----------------------------------------------------------------- @@ -109,19 +303,48 @@ info_filter([Item|Items], Info, Acc) -> %%----------------------------------------------------------------- -log(Log, Packet, Addr, Port) -> +log(#snmp_log{id = Log, seqno = SeqNo}, Packet, Addr, Port) -> ?vtrace("log -> entry with" "~n Log: ~p" "~n Addr: ~p" "~n Port: ~p", [Log, Addr, Port]), - Entry = {timestamp(), Packet, Addr, Port}, - disk_log:alog(Log, Entry). + Entry = make_entry(SeqNo, Packet, Addr, Port), +%% io:format("log -> " +%% "~n Entry: ~p" +%% "~n Info: ~p" +%% "~n", [Entry, disk_log:info(Log)]), + Res = disk_log:alog(Log, Entry), +%% io:format("log -> " +%% "~n Res: ~p" +%% "~n Info: ~p" +%% "~n", [Res, disk_log:info(Log)]), + %% disk_log:sync(Log), + Res. + + + +make_entry(SeqNoGen, Packet, Addr, Port) -> + try next_seqno(SeqNoGen) of + disabled -> + {timestamp(), Packet, Addr, Port}; + {ok, NextSeqNo} -> + {timestamp(), NextSeqNo, Packet, Addr, Port} + catch + _:_ -> + {timestamp(), Packet, Addr, Port} + end. +next_seqno({M, F, A}) -> + {ok, apply(M, F, A)}; +next_seqno(F) when is_function(F) -> + {ok, F()}; +next_seqno(_) -> + disabled. %% -- change_size --- -change_size(Log, NewSize) -> +change_size(#snmp_log{id = Log}, NewSize) -> ?vtrace("change_size -> entry with" "~n Log: ~p" "~n NewSize: ~p", [Log, NewSize]), @@ -171,6 +394,23 @@ log_to_io(Log, FileName, Dir, Mibs, Start, Stop) log_convert(Log, File, Converter). +%% -- log_to_plain --- + +%% log_to_plain(Log, FileName, Dir) -> +%% log_to_plain(Log, FileName, Dir, null, null). + +%% log_to_plain(Log, FileName, Dir, Start) -> +%% log_to_plain(Log, FileName, Dir, Start, null). + +%% log_to_plain(Log, FileName, Dir, Start, Stop) +%% when is_list(Mibs) -> +%% File = filename:join(Dir, FileName), +%% Converter = fun(L) -> +%% do_log_to_plain(L, Start, Stop) +%% end, +%% log_convert(Log, File, Converter). + + %% -------------------------------------------------------------------- %% Internal functions %% -------------------------------------------------------------------- @@ -178,7 +418,12 @@ log_to_io(Log, FileName, Dir, Mibs, Start, Stop) %% -- log_convert --- +log_convert(#snmp_log{id = Log}, File, Converter) -> + do_log_convert(Log, File, Converter); log_convert(Log, File, Converter) -> + do_log_convert(Log, File, Converter). + +do_log_convert(Log, File, Converter) -> %% First check if the caller process has already opened the %% log, because if we close an already open log we will cause %% a runtime error. @@ -274,86 +519,151 @@ loop({Cont, Terms, BadBytes}, Log, Write) -> loop(Error, _Log, _Write) -> Error. -format_msg({TimeStamp, {V3Hdr, ScopedPdu}, {Addr, Port}}, - Mib, Start, Stop) -> - format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port}, - Mib, Start, Stop); -format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port}, - Mib, Start, Stop) -> -% io:format("format_msg -> entry with" -% "~n TimeStamp: ~p" -% "~n Start: ~p" -% "~n Stop: ~p", [TimeStamp, Start, Stop]), - case timestamp_filter(TimeStamp, Start, Stop) of - true -> - case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of - ScopedPDU when is_record(ScopedPDU, scopedPdu) -> - Msg = #message{version = 'version-3', - vsn_hdr = V3Hdr, - data = ScopedPDU}, - f(ts2str(TimeStamp), Msg, Addr, Port, Mib); - {'EXIT', Reason} -> - format_tab("** error in log file at ~s from ~p:~w ~p\n\n", - [ts2str(TimeStamp), ip(Addr), Port, Reason]) - end; - false -> - ignore - end; -format_msg({TimeStamp, Packet, {Addr, Port}}, Mib, Start, Stop) -> - format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop); -format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop) -> + +format_msg(Entry, Mib, Start, Stop) -> + TimeStamp = element(1, Entry), case timestamp_filter(TimeStamp, Start, Stop) of true -> - case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of - Msg when is_record(Msg, message) -> - f(ts2str(TimeStamp), Msg, Addr, Port, Mib); - {'EXIT', Reason} -> - format_tab("** error in log file ~p\n\n", [Reason]) - end; - false -> - ignore - end; -format_msg(_, _Mib, _Start, _Stop) -> + do_format_msg(Entry, Mib); + false -> + ignore + end. + +%% This is an old-style entry, that never had the sequence-number +do_format_msg({Timestamp, Packet, {Addr, Port}}, Mib) -> + do_format_msg(Timestamp, Packet, Addr, Port, Mib); + +%% This is the format without sequence-number +do_format_msg({Timestamp, Packet, Addr, Port}, Mib) -> + do_format_msg(Timestamp, Packet, Addr, Port, Mib); + +%% This is the format with sequence-number +do_format_msg({Timestamp, SeqNo, Packet, Addr, Port}, Mib) -> + do_format_msg(Timestamp, SeqNo, Packet, Addr, Port, Mib); + +%% This is crap... +do_format_msg(_, _) -> format_tab("** unknown entry in log file\n\n", []). -f(TimeStamp, #message{version = Vsn, vsn_hdr = VsnHdr, data = Data}, +do_format_msg(TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port, Mib) -> + case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of + ScopedPDU when is_record(ScopedPDU, scopedPdu) -> + Msg = #message{version = 'version-3', + vsn_hdr = V3Hdr, + data = ScopedPDU}, + f(ts2str(TimeStamp), "", Msg, Addr, Port, Mib); + {'EXIT', Reason} -> + format_tab("** error in log file at ~s from ~p:~w ~p\n\n", + [ts2str(TimeStamp), ip(Addr), Port, Reason]) + end; +do_format_msg(TimeStamp, Packet, Addr, Port, Mib) -> + case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of + Msg when is_record(Msg, message) -> + f(ts2str(TimeStamp), "", Msg, Addr, Port, Mib); + {'EXIT', Reason} -> + format_tab("** error in log file ~p\n\n", [Reason]) + end. + +do_format_msg(TimeStamp, SeqNo, {V3Hdr, ScopedPdu}, Addr, Port, Mib) -> + case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of + ScopedPDU when is_record(ScopedPDU, scopedPdu) -> + Msg = #message{version = 'version-3', + vsn_hdr = V3Hdr, + data = ScopedPDU}, + f(ts2str(TimeStamp), sn2str(SeqNo), Msg, Addr, Port, Mib); + {'EXIT', Reason} -> + format_tab("** error in log file at ~s from ~p:~w ~p\n\n", + [ts2str(TimeStamp), sn2str(SeqNo), + ip(Addr), Port, Reason]) + end; +do_format_msg(TimeStamp, SeqNo, Packet, Addr, Port, Mib) -> + case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of + Msg when is_record(Msg, message) -> + f(ts2str(TimeStamp), sn2str(SeqNo), Msg, Addr, Port, Mib); + {'EXIT', Reason} -> + format_tab("** error in log file ~s from ~p:~w ~p\n\n", + [ts2str(TimeStamp), sn2str(SeqNo), + ip(Addr), Port, Reason]) + end. + + +%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, {Addr, Port}}, +%% Mib, Start, Stop) -> +%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port}, +%% Mib, Start, Stop); +%% format_msg({TimeStamp, {V3Hdr, ScopedPdu}, Addr, Port}, +%% Mib, Start, Stop) -> +%% case timestamp_filter(TimeStamp, Start, Stop) of +%% true -> +%% case (catch snmp_pdus:dec_scoped_pdu(ScopedPdu)) of +%% ScopedPDU when record(ScopedPDU, scopedPdu) -> +%% Msg = #message{version = 'version-3', +%% vsn_hdr = V3Hdr, +%% data = ScopedPDU}, +%% f(ts2str(TimeStamp), Msg, Addr, Port, Mib); +%% {'EXIT', Reason} -> +%% format_tab("** error in log file at ~s from ~p:~w ~p\n\n", +%% [ts2str(TimeStamp), ip(Addr), Port, Reason]) +%% end; +%% false -> +%% ignore +%% end; +%% format_msg({TimeStamp, Packet, {Addr, Port}}, Mib, Start, Stop) -> +%% format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop); +%% format_msg({TimeStamp, Packet, Addr, Port}, Mib, Start, Stop) -> +%% case timestamp_filter(TimeStamp, Start, Stop) of +%% true -> +%% case (catch snmp_pdus:dec_message(binary_to_list(Packet))) of +%% Msg when record(Msg, message) -> +%% f(ts2str(TimeStamp), Msg, Addr, Port, Mib); +%% {'EXIT', Reason} -> +%% format_tab("** error in log file ~p\n\n", [Reason]) +%% end; +%% false -> +%% ignore +%% end; +%% format_msg(_, _Mib, _Start, _Stop) -> +%% format_tab("** unknown entry in log file\n\n", []). + +f(TimeStamp, SeqNo, + #message{version = Vsn, vsn_hdr = VsnHdr, data = Data}, Addr, Port, Mib) -> Str = format_pdu(Data, Mib), HdrStr = format_header(Vsn, VsnHdr), case get_type(Data) of trappdu -> - f_trap(TimeStamp, Vsn, HdrStr, Str, Addr, Port); + f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); 'snmpv2-trap' -> - f_trap(TimeStamp, Vsn, HdrStr, Str, Addr, Port); + f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); 'inform-request' -> - f_inform(TimeStamp, Vsn, HdrStr, Str, Addr, Port); + f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); 'get-response' -> - f_response(TimeStamp, Vsn, HdrStr, Str, Addr, Port); + f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); report -> - f_report(TimeStamp, Vsn, HdrStr, Str, Addr, Port); + f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port); _ -> - f_request(TimeStamp, Vsn, HdrStr, Str, Addr, Port) + f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) end. -f_request(TimeStamp, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("request ~s:~w - ~s [~s] ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, Vsn, Str]). +f_request(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> + format_tab("request ~s:~w - ~s [~s]~s ~w\n~s", + [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). -f_response(TimeStamp, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("response ~s:~w - ~s [~s] ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, Vsn, Str]). +f_response(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> + format_tab("response ~s:~w - ~s [~s]~s ~w\n~s", + [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). -f_report(TimeStamp, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("report ~s:~w - ~s [~s] ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, Vsn, Str]). +f_report(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> + format_tab("report ~s:~w - ~s [~s]~s ~w\n~s", + [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). -f_trap(TimeStamp, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("trap ~s:~w - ~s [~s] ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, Vsn, Str]). +f_trap(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> + format_tab("trap ~s:~w - ~s [~s]~s ~w\n~s", + [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). -f_inform(TimeStamp, Vsn, HdrStr, Str, Addr, Port) -> - format_tab("inform ~s:~w - ~s [~s] ~w\n~s", - [ip(Addr), Port, HdrStr, TimeStamp, Vsn, Str]). +f_inform(TimeStamp, SeqNo, Vsn, HdrStr, Str, Addr, Port) -> + format_tab("inform ~s:~w - ~s [~s]~s ~w\n~s", + [ip(Addr), Port, HdrStr, TimeStamp, SeqNo, Vsn, Str]). %% Convert a timestamp 2-tupple to a printable string @@ -363,6 +673,13 @@ ts2str({Local,Universal}) -> ts2str(_) -> "". +%% Convert a sequence number integer to a printable string +%% +sn2str(SeqNo) when is_integer(SeqNo) -> + " [" ++ integer_to_list(SeqNo) ++ "]"; +sn2str(_) -> + "". + %% Convert a datetime 2-tupple to a printable string %% dat2str({{Y,M,D},{H,Min,S}}) -> @@ -457,19 +774,31 @@ ip({A,B,C,D}) -> %% Various utility functions %% ------------------------------------------------------------------- -log_open(Name, File, Size, Repair, Notify) -> +log_open(Name, File, {M, F, A} = SeqNoGen, Size, Repair, Notify) + when (is_atom(M) andalso is_atom(F) andalso is_list(A)) -> + log_open2(Name, File, SeqNoGen, Size, Repair, Notify); +log_open(Name, File, SeqNoGen, Size, Repair, Notify) + when is_function(SeqNoGen, 0) -> + log_open2(Name, File, SeqNoGen, Size, Repair, Notify); +log_open(Name, File, disabled = SeqNoGen, Size, Repair, Notify) -> + log_open2(Name, File, SeqNoGen, Size, Repair, Notify); +log_open(_, _File, BadSeqNoGen, _Size, _Repair, _Notify) -> + {error, {bad_seqno, BadSeqNoGen}}. + +log_open2(Name, File, SeqNoGen, Size, Repair, Notify) -> case do_log_open(Name, File, Size, Repair, Notify) of {ok, Log} -> - {ok, Log}; + {ok, #snmp_log{id = Log, seqno = SeqNoGen}}; {repaired, Log, Rec, Bad} -> ?vlog("log_open -> repaired: " "~n Rec: ~p" "~n Bad: ~p", [Rec, Bad]), - {ok, Log}; + {ok, #snmp_log{id = Log, seqno = SeqNoGen}}; Error -> Error end. + %% We need to make sure we do not end up in an infinit loop %% Take the number of files of the wrap log and add 2 (for %% the index and size files). diff --git a/lib/snmp/src/misc/snmp_usm.erl b/lib/snmp/src/misc/snmp_usm.erl index 6d216e65d6..19be564a8e 100644 --- a/lib/snmp/src/misc/snmp_usm.erl +++ b/lib/snmp/src/misc/snmp_usm.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-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% %% @@ -206,6 +206,10 @@ des_encrypt(PrivKey, Data, SaltFun) -> des_decrypt(PrivKey, MsgPrivParams, EncData) when length(MsgPrivParams) =:= 8 -> + ?vtrace("des_decrypt -> entry with" + "~n PrivKey: ~p" + "~n MsgPrivParams: ~p" + "~n EncData: ~p", [PrivKey, MsgPrivParams, EncData]), [A,B,C,D,E,F,G,H | PreIV] = PrivKey, DesKey = [A,B,C,D,E,F,G,H], Salt = MsgPrivParams, @@ -213,7 +217,15 @@ des_decrypt(PrivKey, MsgPrivParams, EncData) %% Whatabout errors here??? E.g. not a mulitple of 8! Data = binary_to_list(crypto:des_cbc_decrypt(DesKey, IV, EncData)), Data2 = snmp_pdus:strip_encrypted_scoped_pdu_data(Data), - {ok, Data2}. + {ok, Data2}; +des_decrypt(PrivKey, BadMsgPrivParams, EncData) -> + ?vtrace("des_decrypt -> entry with when bad MsgPrivParams" + "~n PrivKey: ~p" + "~n BadMsgPrivParams: ~p" + "~n EncData: ~p", + [PrivKey, BadMsgPrivParams, EncData]), + throw({error, {bad_msgPrivParams, PrivKey, BadMsgPrivParams, EncData}}). + aes_encrypt(PrivKey, Data, SaltFun) -> AesKey = PrivKey, @@ -225,7 +237,7 @@ aes_encrypt(PrivKey, Data, SaltFun) -> {ok, binary_to_list(EncData), Salt}. aes_decrypt(PrivKey, MsgPrivParams, EncData, EngineBoots, EngineTime) - when length(MsgPrivParams) == 8 -> + when length(MsgPrivParams) =:= 8 -> AesKey = PrivKey, Salt = MsgPrivParams, IV = [?i32(EngineBoots), ?i32(EngineTime) | Salt], |