aboutsummaryrefslogtreecommitdiffstats
path: root/lib/snmp/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/snmp/src')
-rw-r--r--lib/snmp/src/agent/snmpa.erl17
-rw-r--r--lib/snmp/src/agent/snmpa_agent.erl130
-rw-r--r--lib/snmp/src/agent/snmpa_net_if.erl112
-rw-r--r--lib/snmp/src/agent/snmpa_usm.erl18
-rw-r--r--lib/snmp/src/app/snmp.appup.src52
-rw-r--r--lib/snmp/src/manager/snmpm_config.erl62
-rw-r--r--lib/snmp/src/manager/snmpm_net_if.erl66
-rw-r--r--lib/snmp/src/misc/snmp_config.erl144
-rw-r--r--lib/snmp/src/misc/snmp_log.erl495
-rw-r--r--lib/snmp/src/misc/snmp_usm.erl26
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],