From 5b75401dae60c6e3466e011244d9e9c01b9b58ab Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 29 Nov 2011 17:54:46 +0100 Subject: [snmp] Mostly added some more verbosity stuff OTP-9700 --- lib/snmp/src/agent/snmp_target_mib.erl | 16 +++++++- lib/snmp/src/agent/snmpa_agent.erl | 67 ++++++++++++++++++++++++++-------- lib/snmp/src/agent/snmpa_mib_lib.erl | 20 +++++----- lib/snmp/src/agent/snmpa_vacm.erl | 18 ++++++++- lib/snmp/vsn.mk | 6 ++- 5 files changed, 97 insertions(+), 30 deletions(-) diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl index a3ac67b533..d5c4ec2578 100644 --- a/lib/snmp/src/agent/snmp_target_mib.erl +++ b/lib/snmp/src/agent/snmp_target_mib.erl @@ -42,8 +42,14 @@ %% Column not accessible via SNMP - needed when the agent sends informs -define(snmpTargetAddrEngineId, 10). %% Extra comlumns for the augmented table snmpTargetAddrExtTable --define(snmpTargetAddrTMask, 11). --define(snmpTargetAddrMMS, 12). +-define(snmpTargetAddrTMask, 11). +-define(snmpTargetAddrMMS, 12). + +-ifdef(snmp_extended_verbosity). +-define(vt(F,A), ?vtrace(F, A)). +-else. +-define(vt(_F, _A), ok). +-endif. %%----------------------------------------------------------------- @@ -410,10 +416,16 @@ get_target_addrs() -> get_target_addrs(Key, {Tab, _} = TabDb, Acc) -> + ?vt("get_target_addrs -> entry with" + "~n Key: ~p", [Key]), case table_next(Tab, Key) of endOfTable -> + ?vt("get_target_addrs -> endOfTable when" + "~n Acc: ~p", [Acc]), Acc; NextKey -> + ?vt("get_target_addrs -> next ok: " + "~n NextKey: ~p", [NextKey]), case get_target_addr(TabDb, NextKey) of {ok, Targ} -> get_target_addrs(NextKey, TabDb, [Targ| Acc]); diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index f70885b2ec..27e463abf8 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -2767,7 +2767,12 @@ validate_tab_res(_TooMany, [], Mfa, _Res, I) -> %% subagent must be considered to be very rare. %%----------------------------------------------------------------- do_get_next(MibView, UnsortedVarbinds) -> + ?vt("do_get_next -> entry when" + "~n MibView: ~p" + "~n UnsortedVarbinds: ~p", [MibView, UnsortedVarbinds]), SortedVarbinds = oid_sort_varbindlist(UnsortedVarbinds), + ?vt("do_get_next -> " + "~n SortedVarbinds: ~p", [SortedVarbinds]), next_loop_varbinds([], SortedVarbinds, MibView, [], []). oid_sort_varbindlist(Vbs) -> @@ -2780,22 +2785,33 @@ next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb) -> "~n MibView: ~p", [Vb, MibView]), case varbind_next(Vb, MibView) of endOfMibView -> + ?vt("next_loop_varbind -> endOfMibView", []), RVb = if LAVb =:= [] -> Vb; true -> LAVb end, NewVb = RVb#varbind{variabletype = 'NULL', value = endOfMibView}, next_loop_varbinds([], Vbs, MibView, [NewVb | Res], []); + {variable, ME, VarOid} when ((ME#me.access =/= 'not-accessible') andalso (ME#me.access =/= 'write-only') andalso (ME#me.access =/= 'accessible-for-notify')) -> + ?vt("next_loop_varbind -> variable: " + "~n ME: ~p" + "~n VarOid: ~p", [ME, VarOid]), case try_get_instance(Vb, ME) of {value, noValue, _NoSuchSomething} -> + ?vt("next_loop_varbind -> noValue", []), %% Try next one - NewVb = Vb#varbind{oid = VarOid, value = 'NULL'}, + NewVb = Vb#varbind{oid = VarOid, + value = 'NULL'}, next_loop_varbinds([], [NewVb | Vbs], MibView, Res, []); {value, Type, Value} -> - NewVb = Vb#varbind{oid = VarOid, variabletype = Type, - value = Value}, + ?vt("next_loop_varbind -> value" + "~n Type: ~p" + "~n Value: ~p", [Type, Value]), + NewVb = Vb#varbind{oid = VarOid, + variabletype = Type, + value = Value}, next_loop_varbinds([], Vbs, MibView, [NewVb | Res], []); {error, ErrorStatus} -> ?vdebug("next loop varbinds:" @@ -2803,16 +2819,25 @@ next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb) -> {ErrorStatus, Vb#varbind.org_index, []} end; {variable, _ME, VarOid} -> + ?vt("next_loop_varbind -> variable: " + "~n VarOid: ~p", [VarOid]), RVb = if LAVb =:= [] -> Vb; true -> LAVb end, NewVb = Vb#varbind{oid = VarOid, value = 'NULL'}, next_loop_varbinds([], [NewVb | Vbs], MibView, Res, RVb); {table, TableOid, TableRestOid, ME} -> + ?vt("next_loop_varbind -> table: " + "~n TableOid: ~p" + "~n TableRestOid: ~p" + "~n ME: ~p", [TableOid, TableRestOid, ME]), next_loop_varbinds({table, TableOid, ME, [{tab_oid(TableRestOid), Vb}]}, Vbs, MibView, Res, []); {subagent, SubAgentPid, SAOid} -> + ?vt("next_loop_varbind -> subagent: " + "~n SubAgentPid: ~p" + "~n SAOid: ~p", [SubAgentPid, SAOid]), NewVb = Vb#varbind{variabletype = 'NULL', value = 'NULL'}, next_loop_varbinds({subagent, SubAgentPid, SAOid, [NewVb]}, Vbs, MibView, Res, []) @@ -2949,7 +2974,10 @@ next_loop_varbinds([], [], _MibView, Res, _LAVb) -> {noError, 0, Res}. try_get_instance(_Vb, #me{mfa = {M, F, A}, asn1_type = ASN1Type}) -> - ?vtrace("try get instance from <~p,~p,~p>",[M,F,A]), + ?vtrace("try_get_instance -> entry with" + "~n M: ~p" + "~n F: ~p" + "~n A: ~p", [M,F,A]), Result = (catch dbg_apply(M, F, [get | A])), % mib shall return {value, } | % {noValue, noSuchName} (v1) | @@ -2960,6 +2988,7 @@ try_get_instance(_Vb, #me{mfa = {M, F, A}, asn1_type = ASN1Type}) -> tab_oid([]) -> [0]; tab_oid(X) -> X. + %%----------------------------------------------------------------- %% Perform a next, using the varbinds Oid if value is simple %% value. If value is {endOf, NextOid}, use NextOid. @@ -3208,7 +3237,7 @@ next_oid(Oid) -> %%% 5. GET-BULK REQUEST %%%----------------------------------------------------------------- do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) -> - ?vtrace("do get bulk: start with" + ?vtrace("do_get_bulk -> entry with" "~n MibView: ~p" "~n NonRepeaters: ~p" "~n MaxRepetitions: ~p" @@ -3216,12 +3245,12 @@ do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) -> "~n Varbinds: ~p", [MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds]), {NonRepVbs, RestVbs} = split_vbs(NonRepeaters, Varbinds, []), - ?vt("do get bulk -> split: " + ?vt("do_get_bulk -> split: " "~n NonRepVbs: ~p" "~n RestVbs: ~p", [NonRepVbs, RestVbs]), case do_get_next(MibView, NonRepVbs) of {noError, 0, UResNonRepVbs} -> - ?vt("do get bulk -> next: " + ?vt("do_get_bulk -> next noError: " "~n UResNonRepVbs: ~p", [UResNonRepVbs]), ResNonRepVbs = lists:keysort(#varbind.org_index, UResNonRepVbs), %% Decode the first varbinds, produce a reversed list of @@ -3231,7 +3260,7 @@ do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) -> user_err("failed encoding varbind ~w:~n~p", [Idx, Reason]), {genErr, Idx, []}; {SizeLeft, Res} when is_integer(SizeLeft) and is_list(Res) -> - ?vtrace("do get bulk -> encoded: " + ?vtrace("do_get_bulk -> encoded: " "~n SizeLeft: ~p" "~n Res: ~w", [SizeLeft, Res]), case (catch do_get_rep(SizeLeft, MibView, MaxRepetitions, @@ -3244,6 +3273,10 @@ do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) -> ?vtrace("do get bulk -> Res: " "~n ~w", [Res]), {noError, 0, conv_res(Res)}; + {noError, 0, Data} = OK -> + ?vtrace("do get bulk -> OK: " + "~n length(Data): ~w", [length(Data)]), + OK; Else -> ?vtrace("do get bulk -> Else: " "~n ~w", [Else]), @@ -3343,20 +3376,24 @@ do_get_rep(Sz, MibView, Count, Max, Varbinds, Res) -> try_get_bulk(Sz, MibView, Varbinds) -> ?vt("try_get_bulk -> entry with" - "~n Sz: ~w", [Sz]), + "~n Sz: ~w" + "~n MibView: ~w" + "~n Varbinds: ~w", [Sz, MibView, Varbinds]), case do_get_next(MibView, Varbinds) of {noError, 0, UNextVarbinds} -> - ?vt("try_get_bulk -> noError", []), + ?vt("try_get_bulk -> noError: " + "~n UNextVarbinds: ~p", [UNextVarbinds]), NextVarbinds = lists:keysort(#varbind.org_index, UNextVarbinds), case (catch enc_vbs(Sz, NextVarbinds)) of {error, Idx, Reason} -> user_err("failed encoding varbind ~w:~n~p", [Idx, Reason]), - ?vtrace("try_get_bulk -> error: " + ?vtrace("try_get_bulk -> encode error: " "~n Idx: ~p" "~n Reason: ~p", [Idx, Reason]), {genErr, Idx}; - {SizeLeft, Res} when is_integer(SizeLeft) andalso is_list(Res) -> - ?vt("try get bulk -> " + {SizeLeft, Res} when is_integer(SizeLeft) andalso + is_list(Res) -> + ?vt("try get bulk -> encode ok: " "~n SizeLeft: ~w" "~n Res: ~w", [SizeLeft, Res]), {check_end_of_mibview(NextVarbinds), @@ -3367,9 +3404,9 @@ try_get_bulk(Sz, MibView, Varbinds) -> {endOfMibView, [], 0, Res} end; {ErrorStatus, Index, _} -> - ?vt("try get bulk: " + ?vt("try_get_bulk -> error: " "~n ErrorStatus: ~p" - "~n Index: ~p",[ErrorStatus, Index]), + "~n Index: ~p", [ErrorStatus, Index]), {ErrorStatus, Index} end. diff --git a/lib/snmp/src/agent/snmpa_mib_lib.erl b/lib/snmp/src/agent/snmpa_mib_lib.erl index 441228b9ee..ae94aca6d8 100644 --- a/lib/snmp/src/agent/snmpa_mib_lib.erl +++ b/lib/snmp/src/agent/snmpa_mib_lib.erl @@ -60,23 +60,23 @@ table_del_row({Tab, Db} = TabDb, Key) -> get_table(NameDb, FOI) -> (catch get_table(NameDb, FOI, [], [])). -get_table(NameDb, FOI, Oid, Acc) -> - case table_next(NameDb, Oid) of +get_table(NameDb, FOI, Key, Acc) -> + case table_next(NameDb, Key) of endOfTable -> ?vdebug("end of table",[]), {ok, lists:reverse(Acc)}; - Oid -> + Key -> %% Crap, circular ref - ?vinfo("cyclic reference: ~w -> ~w", [Oid,Oid]), - throw({error, {cyclic_db_reference, Oid, Acc}}); - NextOid -> - ?vtrace("get row for oid ~w", [NextOid]), - case table_get_row(NameDb, NextOid, FOI) of + ?vinfo("cyclic reference: ~w -> ~w", [Key, Key]), + throw({error, {cyclic_db_reference, Key, Acc}}); + NextKey -> + ?vtrace("get row for key ~w", [NextKey]), + case table_get_row(NameDb, NextKey, FOI) of undefined -> - throw({error, {invalid_rowindex, NextOid, Acc}}); + throw({error, {invalid_rowindex, NextKey, Acc}}); Row -> ?vtrace("row: ~w", [Row]), - get_table(NameDb, FOI, NextOid, [{NextOid, Row}|Acc]) + get_table(NameDb, FOI, NextKey, [{NextKey, Row}|Acc]) end end. diff --git a/lib/snmp/src/agent/snmpa_vacm.erl b/lib/snmp/src/agent/snmpa_vacm.erl index 2eacea4301..d17ed73ab7 100644 --- a/lib/snmp/src/agent/snmpa_vacm.erl +++ b/lib/snmp/src/agent/snmpa_vacm.erl @@ -62,6 +62,13 @@ get_mib_view(ViewType, SecModel, SecName, SecLevel, ContextName) -> %% Follows the procedure in rfc2275 auth(ViewType, SecModel, SecName, SecLevel, ContextName) -> + ?vtrace("auth -> entry with" + "~n ViewType: ~p" + "~n SecModel: ~p" + "~n SecName: ~p" + "~n SecLevel: ~p" + "~n ContextName: ~p", + [ViewType, SecModel, SecName, SecLevel, ContextName]), % 3.2.1 - Check that the context is known to us ?vdebug("check that the context (~p) is known to us",[ContextName]), case snmp_view_based_acm_mib:vacmContextTable(get, ContextName, @@ -74,7 +81,7 @@ auth(ViewType, SecModel, SecName, SecLevel, ContextName) -> end, % 3.2.2 - Check that the SecModel and SecName is valid ?vdebug("check that SecModel (~p) and SecName (~p) is valid", - [SecModel,SecName]), + [SecModel, SecName]), GroupName = case snmp_view_based_acm_mib:get(vacmSecurityToGroupTable, [SecModel, length(SecName) | SecName], @@ -111,6 +118,8 @@ check_auth(Res) -> {ok, Res}. %% key in the table >= ViewIndex. %%----------------------------------------------------------------- get_mib_view(ViewName) -> + ?vtrace("get_mib_view -> entry with" + "~n ViewName: ~p", [ViewName]), ViewKey = [length(ViewName) | ViewName], case snmp_view_based_acm_mib:table_next(vacmViewTreeFamilyTable, ViewKey) of @@ -202,6 +211,13 @@ backup(BackupDir) -> %% Ret: {ok, ViewName} | {error, Reason} get_view_name(ViewType, GroupName, ContextName, SecModel, SecLevel) -> + ?vtrace("get_view_name -> entry with" + "~n ViewType: ~p" + "~n GroupName: ~p" + "~n ContextName: ~p" + "~n SecModel: ~p" + "~n SecLevel: ~p", + [ViewType, GroupName, ContextName, SecModel, SecLevel]), GroupKey = [length(GroupName) | GroupName], case get_access_row(GroupKey, ContextName, SecModel, SecLevel) of undefined -> diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index 39ec3dc7d4..0bfd5c92ac 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -17,11 +17,13 @@ # # %CopyrightEnd% -SNMP_VSN = 4.17.2 +SNMP_VSN = 4.17.3 PRE_VSN = APP_VSN = "snmp-$(SNMP_VSN)$(PRE_VSN)" -TICKETS = OTP-9236 +TICKETS = OTP-9700 + +TICKETS_4_17_2 = OTP-9236 TICKETS_4_17_1 = OTP-8761 -- cgit v1.2.3 From f47a80465f1c6811faac0d8b0c4f2d206da6fe0f Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 29 Nov 2011 19:06:39 +0100 Subject: [snmp] Correted the expect bug in the snmp test utility This bug will in turn will trigger some other bugs (in the agent), these will be dealt with later. OTP-9700 --- lib/snmp/src/app/snmp.appup.src | 62 +++++++++++- lib/snmp/test/snmp_agent_test_lib.erl | 181 ++++++++++++++++++++++++---------- 2 files changed, 188 insertions(+), 55 deletions(-) diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 6353fc979e..14f413099b 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -22,21 +22,43 @@ %% ----- U p g r a d e ------------------------------------------------------- [ + {"4.17.2", + [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} + ] + }, {"4.17.1", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.17", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, - {update, snmpm_server, soft, soft_purge, soft_purge, []} + {update, snmpm_server, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.16.2", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {load_module, snmp_log, soft_purge, soft_purge, []}, {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, @@ -51,6 +73,10 @@ }, {"4.16.1", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {load_module, snmp_log, soft_purge, soft_purge, []}, {load_module, snmp_pdus, soft_purge, soft_purge, []}, {load_module, snmp_usm, soft_purge, soft_purge, []}, @@ -69,6 +95,10 @@ }, {"4.16", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {load_module, snmp_log, soft_purge, soft_purge, []}, {load_module, snmp_pdus, soft_purge, soft_purge, []}, {load_module, snmp_usm, soft_purge, soft_purge, []}, @@ -92,14 +122,32 @@ %% ------D o w n g r a d e --------------------------------------------------- [ + {"4.17.2", + [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} + ] + }, {"4.17.1", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.17", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, {update, snmpm_server, soft, soft_purge, soft_purge, []} @@ -107,6 +155,10 @@ }, {"4.16.2", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {load_module, snmp_log, soft_purge, soft_purge, []}, {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, @@ -122,6 +174,10 @@ }, {"4.16.1", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {load_module, snmp_log, soft_purge, soft_purge, []}, {load_module, snmp_pdus, soft_purge, soft_purge, []}, {load_module, snmp_usm, soft_purge, soft_purge, []}, @@ -140,6 +196,10 @@ }, {"4.16", [ + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_vacm, soft_purge, soft_purge, []}, + {load_module, snmp_log, soft_purge, soft_purge, []}, {load_module, snmp_pdus, soft_purge, soft_purge, []}, {load_module, snmp_usm, soft_purge, soft_purge, []}, diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl index 9e89aa889c..084b3ee8da 100644 --- a/lib/snmp/test/snmp_agent_test_lib.erl +++ b/lib/snmp/test/snmp_agent_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-2011. 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 @@ -296,7 +296,12 @@ call(N,M,F,A) -> ?DBG("call -> done:" "~n Ret: ~p" "~n Zed: ~p", [Ret, Zed]), - Ret + case Ret of + {error, Reason} -> + exit(Reason); + OK -> + OK + end end. wait(From, Env, M, F, A) -> @@ -724,17 +729,13 @@ expect(Id, A, B, C, D, E) -> expect2(Id, Fun). expect2(Id, F) -> - io:format("~w:expect2 -> entry with" - "~n Id: ~w" - "~n", [?MODULE, Id]), + io:format("EXPECT for ~w~n", [Id]), case F() of {error, Reason} -> - {error, Id, Reason}; + io:format("EXPECT failed for ~w: ~n~p~n", [Id, Reason]), + throw({error, {expect, Id, Reason}}); Else -> - io:format("~w:expect2 -> " - "~n Id: ~w" - "~n Else: ~p" - "~n", [?MODULE, Id, Else]), + io:format("EXPECT result for ~w: ~n~p~n", [Id, Else]), Else end. @@ -769,21 +770,15 @@ do_expect(Expect) when is_atom(Expect) -> do_expect({any_pdu, To}) when is_integer(To) orelse (To =:= infinity) -> - io:format("~w:do_expect(any_pdu) -> entry with" - "~n To: ~w" - "~n", [?MODULE, To]), + io:format("EXPECT any PDU~n", []), receive_pdu(To); do_expect({any_trap, To}) -> - io:format("~w:do_expect(any_trap) -> entry with" - "~n To: ~w" - "~n", [?MODULE, To]), + io:format("EXPECT any TRAP within ~w~n", [To]), receive_trap(To); do_expect({timeout, To}) -> - io:format("~w:do_expect(timeout) -> entry with" - "~n To: ~w" - "~n", [?MODULE, To]), + io:format("EXPECT nothing within ~w~n", [To]), receive X -> {error, {unexpected, X}} @@ -794,13 +789,16 @@ do_expect({timeout, To}) -> do_expect({Err, To}) when is_atom(Err) andalso (is_integer(To) orelse (To =:= infinity)) -> + io:format("EXPECT error ~w within ~w~n", [Err, To]), do_expect({{error, Err}, To}); do_expect({error, Err}) when is_atom(Err) -> Check = fun(_, R) -> R end, + io:format("EXPECT error ~w~n", [Err]), do_expect2(Check, any, Err, any, any, get_timeout()); do_expect({{error, Err}, To}) -> Check = fun(_, R) -> R end, + io:format("EXPECT error ~w within ~w~n", [Err, To]), do_expect2(Check, any, Err, any, any, To); %% exp_varbinds() -> [exp_varbind()] @@ -810,16 +808,25 @@ do_expect({{error, Err}, To}) -> %% ExpVBs -> exp_varbinds() | {VbsCondition, exp_varbinds()} do_expect(ExpVBs) -> Check = fun(_, R) -> R end, + io:format("EXPECT 'get-response'" + "~n with" + "~n Varbinds: ~p~n", [ExpVBs]), do_expect2(Check, 'get-response', noError, 0, ExpVBs, get_timeout()). do_expect(v2trap, ExpVBs) -> Check = fun(_, R) -> R end, + io:format("EXPECT 'snmpv2-trap'" + "~n with" + "~n Varbinds: ~p~n", [ExpVBs]), do_expect2(Check, 'snmpv2-trap', noError, 0, ExpVBs, get_timeout()); do_expect(report, ExpVBs) -> Check = fun(_, R) -> R end, + io:format("EXPECT 'report'" + "~n with" + "~n Varbinds: ~p~n", [ExpVBs]), do_expect2(Check, 'report', noError, 0, ExpVBs, get_timeout()); @@ -827,16 +834,13 @@ do_expect(inform, ExpVBs) -> do_expect({inform, true}, ExpVBs); do_expect({inform, false}, ExpVBs) -> - io:format("~w:do_expect(inform, false) -> entry with" - "~n ExpVBs: ~p" - "~n", [?MODULE, ExpVBs]), Check = fun(_, R) -> R end, + io:format("EXPECT 'inform-request' (false)" + "~n with" + "~n Varbinds: ~p~n", [ExpVBs]), do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()); do_expect({inform, true}, ExpVBs) -> - io:format("~w:do_expect(inform, true) -> entry with" - "~n ExpVBs: ~p" - "~n", [?MODULE, ExpVBs]), Check = fun(PDU, ok) -> RespPDU = PDU#pdu{type = 'get-response', @@ -847,6 +851,9 @@ do_expect({inform, true}, ExpVBs) -> (_, Err) -> Err end, + io:format("EXPECT 'inform-request' (true)" + "~n with" + "~n Varbinds: ~p~n", [ExpVBs]), do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()); do_expect({inform, {error, EStat, EIdx}}, ExpVBs) @@ -861,6 +868,11 @@ do_expect({inform, {error, EStat, EIdx}}, ExpVBs) (_, Err) -> Err end, + io:format("EXPECT 'inform-request' (error)" + "~n with" + "~n Error Status: ~p" + "~n Error Index: ~p" + "~n Varbinds: ~p~n", [EStat, EIdx, ExpVBs]), do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()). @@ -871,6 +883,12 @@ do_expect(Err, Idx, ExpVBs, To) when is_atom(Err) andalso (is_integer(Idx) orelse is_list(Idx) orelse (Idx == any)) -> Check = fun(_, R) -> R end, + io:format("EXPECT 'get-response'" + "~n with" + "~n Error: ~p" + "~n Index: ~p" + "~n Varbinds: ~p" + "~n within ~w~n", [Err, Idx, ExpVBs, To]), do_expect2(Check, 'get-response', Err, Idx, ExpVBs, To). @@ -878,15 +896,13 @@ do_expect(Type, Enterp, Generic, Specific, ExpVBs) -> do_expect(Type, Enterp, Generic, Specific, ExpVBs, 3500). do_expect(trap, Enterp, Generic, Specific, ExpVBs, To) -> - io:format("~w:do_expect(trap) -> entry with" - "~n Enterp: ~w" - "~n Generic: ~w" - "~n Specific: ~w" - "~n ExpVBs: ~w" - "~n To: ~w" - "~nwhen" - "~n Time: ~w" - "~n", [?MODULE, Enterp, Generic, Specific, ExpVBs, To, t()]), + io:format("EXPECT trap" + "~n with" + "~n Enterp: ~w" + "~n Generic: ~w" + "~n Specific: ~w" + "~n Varbinds: ~w" + "~n within ~w~n", [Enterp, Generic, Specific, ExpVBs, To]), PureE = purify_oid(Enterp), case receive_trap(To) of #trappdu{enterprise = PureE, @@ -916,49 +932,51 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To) (is_list(ExpVBs) orelse (ExpVBs =:= any)) andalso (is_integer(To) orelse (To =:= infinity)) -> - io:format("~w:do_expect2 -> entry with" - "~n Type: ~w" - "~n Err: ~w" - "~n Idx: ~w" - "~n ExpVBs: ~w" - "~n To: ~w" - "~nwhen" - "~n Time: ~w" - "~n", [?MODULE, Type, Err, Idx, ExpVBs, To, t()]), - case receive_pdu(To) of #pdu{type = Type, error_status = Err, error_index = Idx} when ExpVBs =:= any -> + io:format("EXPECT received expected pdu (1)~n", []), ok; #pdu{type = Type, request_id = ReqId, error_status = Err2, error_index = Idx} when ExpVBs =:= any -> + io:format("EXPECT received expected pdu with " + "unexpected error status (2): " + "~n Error Status: ~p~n", [Err2]), {error, {unexpected_error_status, Err, Err2, ReqId}}; #pdu{error_status = Err} when (Type =:= any) andalso (Idx =:= any) andalso (ExpVBs =:= any) -> + io:format("EXPECT received expected pdu (3)~n", []), ok; #pdu{request_id = ReqId, error_status = Err2} when (Type =:= any) andalso (Idx =:= any) andalso (ExpVBs =:= any) -> + io:format("EXPECT received expected pdu with " + "unexpected error status (4): " + "~n Error Status: ~p~n", [Err2]), {error, {unexpected_error_status, Err, Err2, ReqId}}; #pdu{type = Type, error_status = Err} when (Idx =:= any) andalso (ExpVBs =:= any) -> + io:format("EXPECT received expected pdu (5)~n", []), ok; #pdu{type = Type, request_id = ReqId, error_status = Err2} when (Idx =:= any) andalso (ExpVBs =:= any) -> + io:format("EXPECT received expected pdu with " + "unexpected error status (6): " + "~n Error Status: ~p~n", [Err2]), {error, {unexpected_error_status, Err, Err2, ReqId}}; #pdu{type = Type, @@ -967,8 +985,13 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To) error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) -> case lists:member(EI, Idx) of true -> + io:format("EXPECT received expected pdu with " + "expected error index (7)~n", []), ok; false -> + io:format("EXPECT received expected pdu with " + "unexpected error index (8): " + "~n Error Index: ~p~n", [EI]), {error, {unexpected_error_index, EI, Idx, ReqId}} end; @@ -978,8 +1001,15 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To) error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) -> case lists:member(EI, Idx) of true -> + io:format("EXPECT received expected pdu with " + "unexpected error status (9): " + "~n Error Status: ~p~n", [Err2]), {error, {unexpected_error_status, Err, Err2, ReqId}}; false -> + io:format("EXPECT received expected pdu with " + "unexpected error (10): " + "~n Error Status: ~p" + "~n Error index: ~p~n", [Err2, EI]), {error, {unexpected_error, {Err, Idx}, {Err2, EI}, ReqId}} end; @@ -987,6 +1017,12 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To) request_id = ReqId, error_status = Err2, error_index = Idx2} when ExpVBs =:= any -> + io:format("EXPECT received unexpected pdu with (11) " + "~n Type: ~p" + "~n ReqId: ~p" + "~n Errot status: ~p" + "~n Error index: ~p" + "~n", [Type2, ReqId, Err2, Idx2]), {error, {unexpected_pdu, {Type, Err, Idx}, {Type2, Err2, Idx2}, ReqId}}; @@ -995,11 +1031,26 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To) error_status = Err, error_index = Idx, varbinds = VBs} = PDU -> + io:format("EXPECT received pdu (12): " + "~n [exp] Type: ~p" + "~n [exp] Error Status: ~p" + "~n [exp] Error Index: ~p" + "~n VBs: ~p" + "~nwhen" + "~n ExpVBs: ~p" + "~n", [Type, Err, Idx, VBs, ExpVBs]), Check(PDU, check_vbs(purify_oids(ExpVBs), VBs)); #pdu{type = Type, error_status = Err, varbinds = VBs} = PDU when Idx =:= any -> + io:format("EXPECT received pdu (13): " + "~n [exp] Type: ~p" + "~n [exp] Error Status: ~p" + "~n VBs: ~p" + "~nwhen" + "~n ExpVBs: ~p" + "~n", [Type, Err, VBs, ExpVBs]), Check(PDU, check_vbs(purify_oids(ExpVBs), VBs)); #pdu{type = Type, @@ -1007,6 +1058,15 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To) error_status = Err, error_index = EI, varbinds = VBs} = PDU when is_list(Idx) -> + io:format("EXPECT received pdu (14): " + "~n [exp] Type: ~p" + "~n ReqId: ~p" + "~n [exp] Error Status: ~p" + "~n [exp] Error Index: ~p" + "~n VBs: ~p" + "~nwhen" + "~n ExpVBs: ~p" + "~n", [Type, ReqId, Err, EI, VBs, ExpVBs]), PureVBs = purify_oids(ExpVBs), case lists:member(EI, Idx) of true -> @@ -1020,6 +1080,13 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To) error_status = Err2, error_index = Idx2, varbinds = VBs2} -> + io:format("EXPECT received unexpected pdu with (15) " + "~n Type: ~p" + "~n ReqId: ~p" + "~n Errot status: ~p" + "~n Error index: ~p" + "~n Varbinds: ~p" + "~n", [Type2, ReqId, Err2, Idx2, VBs2]), {error, {unexpected_pdu, {Type, Err, Idx, purify_oids(ExpVBs)}, @@ -1027,6 +1094,9 @@ do_expect2(Check, Type, Err, Idx, ExpVBs, To) ReqId}}; Error -> + io:format("EXPECT received error (16): " + "~n Error: ~p" + "~n", [Error]), Error end. @@ -1311,10 +1381,12 @@ rewrite_target_addr_conf(Dir, NewPort) -> "~n NewPort: ~p", [NewPort]), TAFile = filename:join(Dir, "target_addr.conf"), case file:read_file_info(TAFile) of - {ok, _} -> ok; - {error, R} -> ?ERR("failure reading file info of " - "target address config file: ~p",[R]), - ok + {ok, _} -> + ok; + {error, R} -> + ?ERR("failure reading file info of " + "target address config file: ~p",[R]), + ok end, ?line [TrapAddr|Addrs] = @@ -1335,8 +1407,9 @@ rewrite_target_addr_conf(Dir, NewPort) -> rewrite_target_addr_conf_check(O) -> {ok,O}. -rewrite_target_addr_conf2(NewPort,{Name,Ip,_Port,Timeout,Retry, - "std_trap",EngineId}) -> +rewrite_target_addr_conf2(NewPort, + {Name, Ip, _Port, Timeout, Retry, + "std_trap", EngineId}) -> ?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]), {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; rewrite_target_addr_conf2(_NewPort,O) -> @@ -1463,7 +1536,7 @@ rpc(Node, F, A) -> %% %% %% t() -> -%% {A,B,C} = erlang:now(), +%% {A,B,C} = os:timestamp(), %% A*1000000000+B*1000+(C div 1000). %% %% @@ -1475,6 +1548,6 @@ rpc(Node, F, A) -> %% Time in milli seconds -t() -> - {A,B,C} = erlang:now(), - A*1000000000+B*1000+(C div 1000). +%% t() -> +%% {A,B,C} = os:timestamp(), +%% A*1000000000+B*1000+(C div 1000). -- cgit v1.2.3 From b4db9877991212cb21f1bf8ac961f5ec3d4f4f1d Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 2 Dec 2011 15:20:16 +0100 Subject: [snmp] Maximum number of varbinds in a Get-BULK response As a means to prevent DoS, maximum number of varbinds in a Get-BULK response has been limited. Also, made some changes to the worker process "API". OTP-9700. --- lib/snmp/src/agent/depend.mk | 2 + lib/snmp/src/agent/snmpa_agent.erl | 423 ++++++++++++++++++++++++-------- lib/snmp/src/agent/snmpa_internal.hrl | 11 +- lib/snmp/src/agent/snmpa_supervisor.erl | 40 ++- 4 files changed, 372 insertions(+), 104 deletions(-) diff --git a/lib/snmp/src/agent/depend.mk b/lib/snmp/src/agent/depend.mk index bc39e1fa35..078ef15821 100644 --- a/lib/snmp/src/agent/depend.mk +++ b/lib/snmp/src/agent/depend.mk @@ -52,6 +52,7 @@ $(EBIN)/snmpa_acm.$(EMULATOR): \ $(EBIN)/snmpa_agent.$(EMULATOR): \ snmpa_agent.erl \ + snmpa_internal.hrl \ ../misc/snmp_debug.hrl \ ../misc/snmp_verbosity.hrl \ ../../include/snmp_types.hrl @@ -136,6 +137,7 @@ $(EBIN)/snmpa_set_lib.$(EMULATOR): \ $(EBIN)/snmpa_supervisor.$(EMULATOR): \ snmpa_supervisor.erl \ + snmpa_internal.hrl \ ../misc/snmp_debug.hrl \ ../misc/snmp_verbosity.hrl diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index 27e463abf8..95199065b3 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -65,7 +65,10 @@ %% Internal exports -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3, tr_var/2, tr_varbind/1, - handle_pdu/7, worker/2, worker_loop/1, do_send_trap/7]). + handle_pdu/8, worker/2, worker_loop/1, do_send_trap/7]). +%% +-export([handle_pdu/7]). +%% -ifndef(default_verbosity). -define(default_verbosity,silence). @@ -81,7 +84,6 @@ -define(DISCO_TERMINATING_TRIGGER_USERNAME, ""). - -ifdef(snmp_debug). -define(GS_START_LINK3(Prio, Parent, Ref, Opts), gen_server:start_link(?MODULE, [Prio, Parent, Ref, Opts], @@ -97,13 +99,48 @@ gen_server:start_link({local, Name}, ?MODULE, [Prio, Parent, Ref, Opts],[])). -endif. - + +%% Increment this whenever a change is made to the worker interface +-define(WORKER_INTERFACE_VERSION, 1). + +%% -- Utility macros for creating worker commands -- +-define(mk_pdu_wreq(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra), + #wrequest{cmd = handle_pdu, + info = [{vsn, Vsn}, + {pdu, Pdu}, + {pdu_ms, PduMS}, + {acm_data, ACMData}, + {addr, Address}, + {gb_max_vbs, GbMaxVBs}, + {extra, Extra}]}. +-define(mk_send_trap_wreq(TrapRec, NotifyName, ContextName, + Recv, Vbs, LocalEngineID), + #wrequest{cmd = handle_pdu, + info = [{trap_rec, TrapRec}, + {notify_name, NotifyName}, + {context_name, ContextName}, + {receiver, Recv}, + {varbinds, Vbs}, + {local_engine_id, LocalEngineID}]}. +-define(mk_terminate_wreq(), #wrequest{cmd = terminate, info = []}). +-define(mk_verbosity_wreq(V), #wrequest{cmd = verbosity, + info = [{verbosity, V}]}). + -record(notification_filter, {id, mod, data}). -record(disco, {from, rec, sender, target, engine_id, sec_level, ctx, ivbs, stage, handler, extra}). +%% This record is used when sending requests to the worker processes +-record(wrequest, + { + version = ?WORKER_INTERFACE_VERSION, + cmd, + info + } + ). + %%----------------------------------------------------------------- %% The agent is multi-threaded, i.e. each request is handled @@ -136,7 +173,8 @@ net_if_mod, backup, disco, - mibs_cache_request}). + mibs_cache_request, + gb_max_vbs}). %%%----------------------------------------------------------------- @@ -324,6 +362,8 @@ do_init(Prio, Parent, Ref, Options) -> MultiT = get_multi_threaded(Options), Vsns = get_versions(Options), + GbMaxVbs = get_gb_max_vbs(Options), + NS = start_note_store(Prio, Ref, Options), {Type, NetIfPid, NetIfMod} = start_net_if(Parent, Prio, Ref, Vsns, NS, Options), @@ -342,7 +382,8 @@ do_init(Prio, Parent, Ref, Options) -> ref = Ref, vsns = Vsns, note_store = NS, - net_if_mod = NetIfMod}}. + net_if_mod = NetIfMod, + gb_max_vbs = GbMaxVbs}}. start_note_store(Prio, Ref, Options) -> @@ -404,7 +445,8 @@ start_net_if(Parent, _Prio, _Ref, _Vsns, _NoteStore, _Options) start_mib_server(Prio, Ref, Mibs, Options) -> ?vdebug("start_mib_server -> with Prio: ~p", [Prio]), MibStorage = get_mib_storage(Options), - MibsOpts = [{mib_storage, MibStorage}|get_option(mib_server, Options, [])], + MibsOpts = [{mib_storage, MibStorage} | + get_option(mib_server, Options, [])], ?vtrace("start_mib_server -> " "~n Mibs: ~p" @@ -734,7 +776,8 @@ handle_info({snmp_pdu, Vsn, Pdu, PduMS, ACMData, Address, Extra}, S) -> ?vdebug("handle_info(snmp_pdu) -> entry with" "~n Vsn: ~p" "~n Pdu: ~p" - "~n Address: ~p", [Vsn, Pdu, Address]), + "~n Address: ~p" + "~n Extra: ~p", [Vsn, Pdu, Address, Extra]), NewS = handle_snmp_pdu(is_valid_pdu_type(Pdu#pdu.type), Vsn, Pdu, PduMS, ACMData, Address, Extra, S), @@ -1005,7 +1048,7 @@ handle_call({subagent_get_next, MibView, Varbinds, PduData}, _From, S) -> "~n PduData: ~p", [MibView,Varbinds,PduData]), put_pdu_data(PduData), - {reply, do_get_next(MibView, Varbinds), S}; + {reply, do_get_next(MibView, Varbinds, infinity), S}; handle_call({subagent_set, Arguments, PduData}, _From, S) -> ?vlog("[handle_call] subagent set:" "~n Arguments: ~p" @@ -1046,7 +1089,7 @@ handle_call({get_next, Vars, Context}, _From, S) -> ?vdebug("Varbinds: ~p",[Varbinds]), MibView = snmpa_acm:get_root_mib_view(), Reply = - case do_get_next(MibView, Varbinds) of + case do_get_next(MibView, Varbinds, infinity) of {noError, 0, NewVarbinds} -> Vbs = lists:keysort(#varbind.org_index, NewVarbinds), [{Oid,Val} || #varbind{oid = Oid, value = Val} <- Vbs]; @@ -1242,15 +1285,15 @@ handle_call(Req, _From, S) -> Reply = {error, {unknown, Req}}, {reply, Reply, S}. -handle_cast({verbosity,Verbosity}, S) -> - ?vlog("verbosity: ~p -> ~p",[get(verbosity),Verbosity]), +handle_cast({verbosity, Verbosity}, S) -> + ?vlog("verbosity: ~p -> ~p",[get(verbosity), Verbosity]), put(verbosity,snmp_verbosity:validate(Verbosity)), case S#state.worker of - Pid when is_pid(Pid) -> Pid ! {verbosity,Verbosity}; + Pid when is_pid(Pid) -> Pid ! ?mk_verbosity_wreq(Verbosity); _ -> ok end, case S#state.set_worker of - Pid2 when is_pid(Pid2) -> Pid2 ! {verbosity,Verbosity}; + Pid2 when is_pid(Pid2) -> Pid2 ! ?mk_verbosity_wreq(Verbosity); _ -> ok end, {noreply, S}; @@ -1337,13 +1380,80 @@ handle_mibs_cache_request(MibServer, Req) -> %% Downgrade %% -%% code_change({down, _Vsn}, S, downgrade_to_pre_4_13) -> -%% {ok, S2}; +code_change({down, _Vsn}, S1, downgrade_to_pre_4_17_3) -> + #state{type = Type, + parent = Parent, + worker = Worker, + worker_state = WorkerState, + set_worker = SetWorker, + multi_threaded = MT, + ref = Ref, + vsns = Vsns, + nfilters = NF, + note_store = NoteStore, + mib_server = MS, + net_if = NetIf, + net_if_mod = NetIfMod, + backup = Backup, + disco = Disco, + mibs_cache_request = MCR} = S1, + S2 = {state, + type = Type, + parent = Parent, + worker = Worker, + worker_state = WorkerState, + set_worker = SetWorker, + multi_threaded = MT, + ref = Ref, + vsns = Vsns, + nfilters = NF, + note_store = NoteStore, + mib_server = MS, + net_if = NetIf, + net_if_mod = NetIfMod, + backup = Backup, + disco = Disco, + mibs_cache_request = MCR}, + {ok, S2}; %% Upgrade %% -%% code_change(_Vsn, S, upgrade_from_pre_4_13) -> -%% {ok, S2}; +code_change(_Vsn, S1, upgrade_from_pre_4_17_3) -> + {state, + type = Type, + parent = Parent, + worker = Worker, + worker_state = WorkerState, + set_worker = SetWorker, + multi_threaded = MT, + ref = Ref, + vsns = Vsns, + nfilters = NF, + note_store = NoteStore, + mib_server = MS, + net_if = NetIf, + net_if_mod = NetIfMod, + backup = Backup, + disco = Disco, + mibs_cache_request = MCR} = S1, + S2 = #state{type = Type, + parent = Parent, + worker = Worker, + worker_state = WorkerState, + set_worker = SetWorker, + multi_threaded = MT, + ref = Ref, + vsns = Vsns, + nfilters = NF, + note_store = NoteStore, + mib_server = MS, + net_if = NetIf, + net_if_mod = NetIfMod, + backup = Backup, + disco = Disco, + mibs_cache_request = MCR, + gb_max_vbs = ?DEFAULT_GB_MAX_VBS}, + {ok, S2}; code_change(_Vsn, S, _Extra) -> {ok, S}. @@ -1383,7 +1493,7 @@ worker_start(Dict) -> %% worker_stop(Pid, infinity). worker_stop(Pid, Timeout) when is_pid(Pid) -> - Pid ! terminate, + Pid ! ?mk_terminate_wreq(), receive {'EXIT', Pid, normal} -> ok @@ -1517,9 +1627,11 @@ invalidate_ca_cache() -> %% %%----------------------------------------------------------------- -spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, Extra) -> +%% This functions spawns a temporary worker process, +%% that evaluates one request and then silently exits. +spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra) -> Dict = get(), - Args = [Vsn, Pdu, PduMS, ACMData, Address, Extra, Dict], + Args = [Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra, Dict], proc_lib:spawn_link(?MODULE, handle_pdu, Args). spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, Vbs, @@ -1532,7 +1644,7 @@ spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, Vbs, do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, Dict) -> lists:foreach(fun({Key, Val}) -> put(Key, Val) end, Dict), - put(sname,trap_sender_short_name(get(sname))), + put(sname, trap_sender_short_name(get(sname))), ?vlog("starting",[]), snmpa_trap:send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, get(net_if)). @@ -1545,9 +1657,56 @@ worker(Master, Dict) -> worker_loop(Master) -> receive + #wrequest{cmd = handle_pdu, + info = Info} -> + ?vtrace("worker_loop -> received handle_pdu request", []), + Vsn = proplists:get_value(vsn, Info), + Pdu = proplists:get_value(pdu, Info), + PduMS = proplists:get_value(pdu_ms, Info), + ACMData = proplists:get_value(acm_data, Info), + Address = proplists:get_value(addr, Info), + GbMaxVBs = proplists:get_value(gb_max_vbs, Info), + Extra = proplists:get_value(extra, Info), + handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra), + ok; + + + #wrequest{cmd = send_trap, + info = Info} -> + ?vtrace("worker_loop -> send trap", []), + TrapRec = proplists:get_value(trap_rec, Info), + NotifyName = proplists:get_value(notify_name, Info), + ContextName = proplists:get_value(context_name, Info), + Recv = proplists:get_value(receiver, Info), + Vbs = proplists:get_value(vbs, Info), + LocalEngineID = proplists:get_value(local_engine_id, Info), + snmpa_trap:send_trap(TrapRec, NotifyName, + ContextName, Recv, Vbs, LocalEngineID, + get(net_if)), + ok; + + + #wrequest{cmd = verbosity, + info = Info} -> + Verbosity = proplists:get_value(verbosity, Info), + put(verbosity, snmp_verbosity:validate(Verbosity)), + ok; + + + #wrequest{cmd = terminate} -> + exit(normal); + + + %% ************************************************************* + %% + %% Kept for backward compatibillity reasons + %% + %% ************************************************************* + {Vsn, Pdu, PduMS, ACMData, Address, Extra} -> ?vtrace("worker_loop -> received request", []), - handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra), + handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, + ?DEFAULT_GB_MAX_VBS, Extra), Master ! worker_available; %% We don't trap exits! @@ -1590,42 +1749,53 @@ worker_loop(Master) -> %%----------------------------------------------------------------- handle_snmp_pdu(true, Vsn, Pdu, PduMS, ACMData, Address, Extra, - #state{multi_threaded = false} = S) -> + #state{multi_threaded = false, + gb_max_vbs = GbMaxVBs} = S) -> ?vtrace("handle_snmp_pdu -> single-thread agent",[]), - handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra), + handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra), S; handle_snmp_pdu(true, Vsn, #pdu{type = 'set-request'} = Pdu, PduMS, ACMData, Address, Extra, - #state{set_worker = Worker} = S) -> + #state{set_worker = Worker, + gb_max_vbs = GbMaxVBs} = S) -> ?vtrace("handle_snmp_pdu -> multi-thread agent: " "send set-request to main worker",[]), - Worker ! {Vsn, Pdu, PduMS, ACMData, Address, Extra}, + WRequest = ?mk_pdu_wreq(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra), + Worker ! WRequest, S#state{worker_state = busy}; handle_snmp_pdu(true, Vsn, Pdu, PduMS, ACMData, Address, Extra, - #state{worker_state = busy} = S) -> + #state{worker_state = busy, + gb_max_vbs = GbMaxVBs} = S) -> ?vtrace("handle_snmp_pdu -> multi-thread agent: " "main worker busy - create new worker",[]), - spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, Extra), + spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra), S; handle_snmp_pdu(true, Vsn, Pdu, PduMS, ACMData, Address, Extra, - #state{worker = Worker} = S) -> + #state{worker = Worker, + gb_max_vbs = GbMaxVBs} = S) -> ?vtrace("handle_snmp_pdu -> multi-thread agent: " "send to main worker",[]), - Worker ! {Vsn, Pdu, PduMS, ACMData, Address, Extra}, + WRequest = ?mk_pdu_wreq(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra), + Worker ! WRequest, S#state{worker_state = busy}; handle_snmp_pdu(_, _Vsn, _Pdu, _PduMS, _ACMData, _Address, _Extra, S) -> S. %% Called via the spawn_thread function +%% handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra, Dict) -> + handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, ?DEFAULT_GB_MAX_VBS, Extra, + Dict). +%% +handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra, Dict) -> lists:foreach(fun({Key, Val}) -> put(Key, Val) end, Dict), put(sname, pdu_handler_short_name(get(sname))), ?vlog("new worker starting",[]), - handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra). + handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra). -handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra) -> +handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra) -> %% OTP-3324 AuthMod = get(auth_module), case AuthMod:init_check_access(Pdu, ACMData) of @@ -1634,7 +1804,8 @@ handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra) -> "~n MibView: ~p" "~n ContextName: ~p", [MibView, ContextName]), AgentData = cheat(ACMData, Address, ContextName), - do_handle_pdu(MibView, Vsn, Pdu, PduMS, ACMData, AgentData, Extra); + do_handle_pdu(MibView, Vsn, Pdu, PduMS, ACMData, AgentData, + GbMaxVBs, Extra); {error, Reason} -> ?vlog("handle_pdu -> error:" "~n Reason: ~p", [Reason]), @@ -1648,16 +1819,19 @@ handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra) -> end. do_handle_pdu(MibView, Vsn, Pdu, PduMS, - ACMData, {Community, Address, ContextName}, Extra) -> + ACMData, {Community, Address, ContextName}, + GbMaxVBs, Extra) -> put(net_if_data, Extra), + RePdu = process_msg(MibView, Vsn, Pdu, PduMS, Community, - Address, ContextName), + Address, ContextName, GbMaxVBs), ?vtrace("do_handle_pdu -> processed:" "~n RePdu: ~p", [RePdu]), - get(net_if) ! {snmp_response, Vsn, RePdu, - RePdu#pdu.type, ACMData, Address, Extra}. + NetIf = get(net_if), + NetIf ! {snmp_response, Vsn, RePdu, + RePdu#pdu.type, ACMData, Address, Extra}. handle_acm_error(Vsn, Reason, Pdu, ACMData, Address, Extra) -> @@ -1831,9 +2005,9 @@ do_handle_send_trap(S, TrapRec, NotifyName, ContextName, Recv, Varbinds, master_agent -> %% Send to main worker ?vtrace("do_handle_send_trap -> send to main worker",[]), - S#state.worker ! {send_trap, - TrapRec, NotifyName, ContextName, Recv, Vbs, - LocalEngineID}, + S#state.worker ! ?mk_send_trap_wreq(TrapRec, NotifyName, + ContextName, Recv, Vbs, + LocalEngineID), {ok, S#state{worker_state = busy}} end. @@ -2170,17 +2344,18 @@ handle_mib_of(MibServer, Oid) -> %% Func: process_msg/7 %% Returns: RePdu %%----------------------------------------------------------------- -process_msg(MibView, Vsn, Pdu, PduMS, Community, {Ip, Udp}, ContextName) -> +process_msg(MibView, Vsn, Pdu, PduMS, Community, {Ip, Udp}, ContextName, + GbMaxVBs) -> #pdu{request_id = ReqId} = Pdu, put(snmp_address, {tuple_to_list(Ip), Udp}), put(snmp_request_id, ReqId), put(snmp_community, Community), put(snmp_context, ContextName), ?vtrace("process ~p",[Pdu#pdu.type]), - process_pdu(Pdu, PduMS, Vsn, MibView). + process_pdu(Pdu, PduMS, Vsn, MibView, GbMaxVBs). process_pdu(#pdu{type='get-request', request_id = ReqId, varbinds=Vbs}, - _PduMS, Vsn, MibView) -> + _PduMS, Vsn, MibView, _GbMaxVBs) -> ?vtrace("get ~p",[ReqId]), Res = get_err(do_get(MibView, Vbs, false)), ?vtrace("get result: " @@ -2201,12 +2376,12 @@ process_pdu(#pdu{type='get-request', request_id = ReqId, varbinds=Vbs}, make_response_pdu(ReqId, ErrStatus, ErrIndex, Vbs, ResponseVarbinds); process_pdu(#pdu{type = 'get-next-request', request_id = ReqId, varbinds = Vbs}, - _PduMS, Vsn, MibView) -> + _PduMS, Vsn, MibView, _GbMaxVBs) -> ?vtrace("process get-next-request -> entry with" "~n ReqId: ~p" "~n Vbs: ~p" "~n MibView: ~p",[ReqId, Vbs, MibView]), - Res = get_err(do_get_next(MibView, Vbs)), + Res = get_err(do_get_next(MibView, Vbs, infinity)), ?vtrace("get-next result: " "~n ~p",[Res]), {ErrStatus, ErrIndex, ResVarbinds} = @@ -2223,11 +2398,15 @@ process_pdu(#pdu{type = 'get-next-request', request_id = ReqId, varbinds = Vbs}, "~n ~p",[ResponseVarbinds]), make_response_pdu(ReqId, ErrStatus, ErrIndex, Vbs, ResponseVarbinds); -process_pdu(#pdu{type = 'get-bulk-request',request_id = ReqId,varbinds = Vbs, - error_status = NonRepeaters, error_index = MaxRepetitions}, - PduMS, _Vsn, MibView)-> +process_pdu(#pdu{type = 'get-bulk-request', + request_id = ReqId, + varbinds = Vbs, + error_status = NonRepeaters, + error_index = MaxRepetitions}, + PduMS, _Vsn, MibView, GbMaxVBs) -> {ErrStatus, ErrIndex, ResponseVarbinds} = - get_err(do_get_bulk(MibView,NonRepeaters,MaxRepetitions,PduMS,Vbs)), + get_err(do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Vbs, + GbMaxVBs)), ?vtrace("get-bulk final result: " "~n Error status: ~p" "~n Error index: ~p" @@ -2236,7 +2415,7 @@ process_pdu(#pdu{type = 'get-bulk-request',request_id = ReqId,varbinds = Vbs, make_response_pdu(ReqId, ErrStatus, ErrIndex, Vbs, ResponseVarbinds); process_pdu(#pdu{type = 'set-request', request_id = ReqId, varbinds = Vbs}, - _PduMS, Vsn, MibView)-> + _PduMS, Vsn, MibView, _GbMaxVbs)-> Res = do_set(MibView, Vbs), ?vtrace("set result: " "~n ~p",[Res]), @@ -2293,7 +2472,8 @@ validate_next_v1_2([Vb | _Vbs], _MibView, _Res) {noSuchName, Vb#varbind.org_index}; validate_next_v1_2([Vb | Vbs], MibView, Res) when Vb#varbind.variabletype =:= 'Counter64' -> - case validate_next_v1(do_get_next(MibView, [mk_next_oid(Vb)]), MibView) of + case validate_next_v1( + do_get_next(MibView, [mk_next_oid(Vb)], infinity), MibView) of {noError, 0, [NVb]} -> validate_next_v1_2(Vbs, MibView, [NVb | Res]); {Error, Index, _OrgVb} -> @@ -2766,20 +2946,31 @@ validate_tab_res(_TooMany, [], Mfa, _Res, I) -> %% that this really matters, since many nexts across the same %% subagent must be considered to be very rare. %%----------------------------------------------------------------- -do_get_next(MibView, UnsortedVarbinds) -> + +%% It may be a bit agressive to check this already, +%% but since it is a security measure, it makes sense. +do_get_next(_MibView, UnsortedVarbinds, GbMaxVBs) + when (is_integer(GbMaxVBs) andalso (length(UnsortedVarbinds) > GbMaxVBs)) -> + {tooBig, 0, []}; % What is the correct index in this case? +do_get_next(MibView, UnsortedVBs, GbMaxVBs) -> ?vt("do_get_next -> entry when" "~n MibView: ~p" - "~n UnsortedVarbinds: ~p", [MibView, UnsortedVarbinds]), - SortedVarbinds = oid_sort_varbindlist(UnsortedVarbinds), + "~n UnsortedVBs: ~p", [MibView, UnsortedVBs]), + SortedVBs = oid_sort_vbs(UnsortedVBs), ?vt("do_get_next -> " - "~n SortedVarbinds: ~p", [SortedVarbinds]), - next_loop_varbinds([], SortedVarbinds, MibView, [], []). + "~n SortedVBs: ~p", [SortedVBs]), + next_loop_varbinds([], SortedVBs, MibView, [], [], GbMaxVBs). -oid_sort_varbindlist(Vbs) -> +oid_sort_vbs(Vbs) -> lists:keysort(#varbind.oid, Vbs). +next_loop_varbinds(_, Vbs, _MibView, Res, _LAVb, GbMaxVBs) + when (is_integer(GbMaxVBs) andalso + ((length(Vbs) + length(Res)) > GbMaxVBs)) -> + {tooBig, 0, []}; % What is the correct index in this case? + %% LAVb is Last Accessible Vb -next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb) -> +next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb, GbMaxVBs) -> ?vt("next_loop_varbinds -> entry when" "~n Vb: ~p" "~n MibView: ~p", [Vb, MibView]), @@ -2790,7 +2981,7 @@ next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb) -> true -> LAVb end, NewVb = RVb#varbind{variabletype = 'NULL', value = endOfMibView}, - next_loop_varbinds([], Vbs, MibView, [NewVb | Res], []); + next_loop_varbinds([], Vbs, MibView, [NewVb | Res], [], GbMaxVBs); {variable, ME, VarOid} when ((ME#me.access =/= 'not-accessible') andalso (ME#me.access =/= 'write-only') andalso @@ -2804,7 +2995,8 @@ next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb) -> %% Try next one NewVb = Vb#varbind{oid = VarOid, value = 'NULL'}, - next_loop_varbinds([], [NewVb | Vbs], MibView, Res, []); + next_loop_varbinds([], [NewVb | Vbs], MibView, Res, [], + GbMaxVBs); {value, Type, Value} -> ?vt("next_loop_varbind -> value" "~n Type: ~p" @@ -2812,7 +3004,8 @@ next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb) -> NewVb = Vb#varbind{oid = VarOid, variabletype = Type, value = Value}, - next_loop_varbinds([], Vbs, MibView, [NewVb | Res], []); + next_loop_varbinds([], Vbs, MibView, [NewVb | Res], [], + GbMaxVBs); {error, ErrorStatus} -> ?vdebug("next loop varbinds:" "~n ErrorStatus: ~p",[ErrorStatus]), @@ -2825,7 +3018,7 @@ next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb) -> true -> LAVb end, NewVb = Vb#varbind{oid = VarOid, value = 'NULL'}, - next_loop_varbinds([], [NewVb | Vbs], MibView, Res, RVb); + next_loop_varbinds([], [NewVb | Vbs], MibView, Res, RVb, GbMaxVBs); {table, TableOid, TableRestOid, ME} -> ?vt("next_loop_varbind -> table: " "~n TableOid: ~p" @@ -2833,17 +3026,17 @@ next_loop_varbinds([], [Vb | Vbs], MibView, Res, LAVb) -> "~n ME: ~p", [TableOid, TableRestOid, ME]), next_loop_varbinds({table, TableOid, ME, [{tab_oid(TableRestOid), Vb}]}, - Vbs, MibView, Res, []); + Vbs, MibView, Res, [], GbMaxVBs); {subagent, SubAgentPid, SAOid} -> ?vt("next_loop_varbind -> subagent: " "~n SubAgentPid: ~p" "~n SAOid: ~p", [SubAgentPid, SAOid]), NewVb = Vb#varbind{variabletype = 'NULL', value = 'NULL'}, next_loop_varbinds({subagent, SubAgentPid, SAOid, [NewVb]}, - Vbs, MibView, Res, []) + Vbs, MibView, Res, [], GbMaxVBs) end; next_loop_varbinds({table, TableOid, ME, TabOids}, - [Vb | Vbs], MibView, Res, _LAVb) -> + [Vb | Vbs], MibView, Res, _LAVb, GbMaxVBs) -> ?vt("next_loop_varbinds(table) -> entry with" "~n TableOid: ~p" "~n Vb: ~p", [TableOid, Vb]), @@ -2851,13 +3044,14 @@ next_loop_varbinds({table, TableOid, ME, TabOids}, {table, TableOid, TableRestOid, _ME} -> next_loop_varbinds({table, TableOid, ME, [{tab_oid(TableRestOid), Vb} | TabOids]}, - Vbs, MibView, Res, []); + Vbs, MibView, Res, [], GbMaxVBs); _ -> case get_next_table(ME, TableOid, TabOids, MibView) of {ok, TabRes, TabEndOfTabVbs} -> NewVbs = lists:append(TabEndOfTabVbs, [Vb | Vbs]), NewRes = lists:append(TabRes, Res), - next_loop_varbinds([], NewVbs, MibView, NewRes, []); + next_loop_varbinds([], NewVbs, MibView, NewRes, [], + GbMaxVBs); {ErrorStatus, OrgIndex} -> ?vdebug("next loop varbinds: next varbind" "~n ErrorStatus: ~p" @@ -2867,7 +3061,7 @@ next_loop_varbinds({table, TableOid, ME, TabOids}, end end; next_loop_varbinds({table, TableOid, ME, TabOids}, - [], MibView, Res, _LAVb) -> + [], MibView, Res, _LAVb, GbMaxVBs) -> ?vt("next_loop_varbinds(table) -> entry with" "~n TableOid: ~p", [TableOid]), case get_next_table(ME, TableOid, TabOids, MibView) of @@ -2876,7 +3070,8 @@ next_loop_varbinds({table, TableOid, ME, TabOids}, "~n TabRes: ~p" "~n TabEndOfTabVbs: ~p", [TabRes, TabEndOfTabVbs]), NewRes = lists:append(TabRes, Res), - next_loop_varbinds([], TabEndOfTabVbs, MibView, NewRes, []); + next_loop_varbinds([], TabEndOfTabVbs, MibView, NewRes, [], + GbMaxVBs); {ErrorStatus, OrgIndex} -> ?vdebug("next loop varbinds: next table" "~n ErrorStatus: ~p" @@ -2885,7 +3080,7 @@ next_loop_varbinds({table, TableOid, ME, TabOids}, {ErrorStatus, OrgIndex, []} end; next_loop_varbinds({subagent, SAPid, SAOid, SAVbs}, - [Vb | Vbs], MibView, Res, _LAVb) -> + [Vb | Vbs], MibView, Res, _LAVb, GbMaxVBs) -> ?vt("next_loop_varbinds(subagent) -> entry with" "~n SAPid: ~p" "~n SAOid: ~p" @@ -2894,13 +3089,14 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs}, {subagent, _SubAgentPid, SAOid} -> next_loop_varbinds({subagent, SAPid, SAOid, [Vb | SAVbs]}, - Vbs, MibView, Res, []); + Vbs, MibView, Res, [], GbMaxVBs); _ -> case get_next_sa(SAPid, SAOid, SAVbs, MibView) of {ok, SARes, SAEndOfMibViewVbs} -> NewVbs = lists:append(SAEndOfMibViewVbs, [Vb | Vbs]), NewRes = lists:append(SARes, Res), - next_loop_varbinds([], NewVbs, MibView, NewRes, []); + next_loop_varbinds([], NewVbs, MibView, NewRes, [], + GbMaxVBs); {noSuchName, OrgIndex} -> %% v1 reply, treat this Vb as endOfMibView, and try again %% for the others. @@ -2913,12 +3109,14 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs}, case lists:delete(EVb, SAVbs) of [] -> next_loop_varbinds([], [EndOfVb, Vb | Vbs], - MibView, Res, []); + MibView, Res, [], + GbMaxVBs); TryAgainVbs -> next_loop_varbinds({subagent, SAPid, SAOid, TryAgainVbs}, [EndOfVb, Vb | Vbs], - MibView, Res, []) + MibView, Res, [], + GbMaxVBs) end; false -> %% bad index from subagent @@ -2934,14 +3132,15 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs}, end end; next_loop_varbinds({subagent, SAPid, SAOid, SAVbs}, - [], MibView, Res, _LAVb) -> + [], MibView, Res, _LAVb, GbMaxVBs) -> ?vt("next_loop_varbinds(subagent) -> entry with" "~n SAPid: ~p" "~n SAOid: ~p", [SAPid, SAOid]), case get_next_sa(SAPid, SAOid, SAVbs, MibView) of {ok, SARes, SAEndOfMibViewVbs} -> NewRes = lists:append(SARes, Res), - next_loop_varbinds([], SAEndOfMibViewVbs, MibView, NewRes, []); + next_loop_varbinds([], SAEndOfMibViewVbs, MibView, NewRes, [], + GbMaxVBs); {noSuchName, OrgIndex} -> %% v1 reply, treat this Vb as endOfMibView, and try again for %% the others. @@ -2952,11 +3151,13 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs}, value = {endOfMibView, NextOid}}, case lists:delete(EVb, SAVbs) of [] -> - next_loop_varbinds([], [EndOfVb], MibView, Res, []); + next_loop_varbinds([], [EndOfVb], MibView, Res, [], + GbMaxVBs); TryAgainVbs -> next_loop_varbinds({subagent, SAPid, SAOid, TryAgainVbs}, - [EndOfVb], MibView, Res, []) + [EndOfVb], MibView, Res, [], + GbMaxVBs) end; false -> %% bad index from subagent @@ -2969,7 +3170,7 @@ next_loop_varbinds({subagent, SAPid, SAOid, SAVbs}, [ErrorStatus,OrgIndex]), {ErrorStatus, OrgIndex, []} end; -next_loop_varbinds([], [], _MibView, Res, _LAVb) -> +next_loop_varbinds([], [], _MibView, Res, _LAVb, _GbMaxVBs) -> ?vt("next_loop_varbinds -> entry when done", []), {noError, 0, Res}. @@ -3235,21 +3436,29 @@ next_oid(Oid) -> %%%----------------------------------------------------------------- %%% 5. GET-BULK REQUEST +%%% +%%% In order to prevent excesses in reply sizes there are two +%%% preventive methods in place. One is to check that the encode +%%% size does not exceed Max PDU size (this is mentioned in the +%%% standard). The other is a simple VBs limit. That is, the +%%% resulting response cannot contain more then this number of VBs. %%%----------------------------------------------------------------- -do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) -> + +do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds, GbMaxVBs) -> ?vtrace("do_get_bulk -> entry with" "~n MibView: ~p" "~n NonRepeaters: ~p" "~n MaxRepetitions: ~p" "~n PduMS: ~p" - "~n Varbinds: ~p", - [MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds]), + "~n Varbinds: ~p" + "~n GbMaxVBs: ~p", + [MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds, GbMaxVBs]), {NonRepVbs, RestVbs} = split_vbs(NonRepeaters, Varbinds, []), ?vt("do_get_bulk -> split: " "~n NonRepVbs: ~p" "~n RestVbs: ~p", [NonRepVbs, RestVbs]), - case do_get_next(MibView, NonRepVbs) of - {noError, 0, UResNonRepVbs} -> + case do_get_next(MibView, NonRepVbs, GbMaxVBs) of + {noError, 0, UResNonRepVbs} -> ?vt("do_get_bulk -> next noError: " "~n UResNonRepVbs: ~p", [UResNonRepVbs]), ResNonRepVbs = lists:keysort(#varbind.org_index, UResNonRepVbs), @@ -3264,7 +3473,8 @@ do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) -> "~n SizeLeft: ~p" "~n Res: ~w", [SizeLeft, Res]), case (catch do_get_rep(SizeLeft, MibView, MaxRepetitions, - RestVbs, Res)) of + RestVbs, Res, + length(UResNonRepVbs), GbMaxVBs)) of {error, Idx, Reason} -> user_err("failed encoding varbind ~w:~n~p", [Idx, Reason]), @@ -3285,6 +3495,7 @@ do_get_bulk(MibView, NonRepeaters, MaxRepetitions, PduMS, Varbinds) -> Res when is_list(Res) -> {noError, 0, conv_res(Res)} end; + {ErrorStatus, Index, _} -> ?vdebug("do get bulk: " "~n ErrorStatus: ~p" @@ -3334,11 +3545,12 @@ enc_vbs(SizeLeft, Vbs) -> end, lists:foldl(Fun, {SizeLeft, []}, Vbs). -do_get_rep(Sz, MibView, MaxRepetitions, Varbinds, Res) +do_get_rep(Sz, MibView, MaxRepetitions, Varbinds, Res, GbNumVBs, GbMaxVBs) when MaxRepetitions >= 0 -> - do_get_rep(Sz, MibView, 0, MaxRepetitions, Varbinds, Res); -do_get_rep(Sz, MibView, _MaxRepetitions, Varbinds, Res) -> - do_get_rep(Sz, MibView, 0, 0, Varbinds, Res). + do_get_rep(Sz, MibView, 0, MaxRepetitions, Varbinds, Res, + GbNumVBs, GbMaxVBs); +do_get_rep(Sz, MibView, _MaxRepetitions, Varbinds, Res, GbNumVBs, GbMaxVBs) -> + do_get_rep(Sz, MibView, 0, 0, Varbinds, Res, GbNumVBs, GbMaxVBs). conv_res(ResVarbinds) -> conv_res(ResVarbinds, []). @@ -3347,22 +3559,30 @@ conv_res([VbListOfBytes | T], Bytes) -> conv_res([], Bytes) -> Bytes. -do_get_rep(_Sz, _MibView, Max, Max, _, Res) -> +%% The only only other value, then a positive integer, is infinity. +do_get_rep(_Sz, _MibView, Count, Max, _, _Res, GbNumVBs, GbMaxVBs) + when (is_integer(GbMaxVBs) andalso (GbNumVBs > GbMaxVBs)) -> + ?vinfo("Max Get-BULK VBs limit (~w) exceeded (~w) when:" + "~n Count: ~p" + "~n Max: ~p", [GbMaxVBs, GbNumVBs, Count, Max]), + {tooBig, 0, []}; +do_get_rep(_Sz, _MibView, Max, Max, _, Res, _GbNumVBs, _GbMaxVBs) -> ?vt("do_get_rep -> done when: " "~n Res: ~p", [Res]), {noError, 0, conv_res(Res)}; -do_get_rep(Sz, MibView, Count, Max, Varbinds, Res) -> +do_get_rep(Sz, MibView, Count, Max, Varbinds, Res, GbNumVBs, GbMaxVBs) -> ?vt("do_get_rep -> entry when: " "~n Sz: ~p" "~n Count: ~p" "~n Res: ~w", [Sz, Count, Res]), - case try_get_bulk(Sz, MibView, Varbinds) of + case try_get_bulk(Sz, MibView, Varbinds, GbMaxVBs) of {noError, NextVarbinds, SizeLeft, Res2} -> ?vt("do_get_rep -> noError: " "~n SizeLeft: ~p" "~n Res2: ~p", [SizeLeft, Res2]), do_get_rep(SizeLeft, MibView, Count+1, Max, NextVarbinds, - Res2 ++ Res); + Res2 ++ Res, + GbNumVBs + length(Varbinds), GbMaxVBs); {endOfMibView, _NextVarbinds, _SizeLeft, Res2} -> ?vt("do_get_rep -> endOfMibView: " "~n Res2: ~p", [Res2]), @@ -3374,16 +3594,19 @@ do_get_rep(Sz, MibView, Count, Max, Varbinds, Res) -> {ErrorStatus, Index, []} end. -try_get_bulk(Sz, MibView, Varbinds) -> +org_index_sort_vbs(Vbs) -> + lists:keysort(#varbind.org_index, Vbs). + +try_get_bulk(Sz, MibView, Varbinds, GbMaxVBs) -> ?vt("try_get_bulk -> entry with" "~n Sz: ~w" "~n MibView: ~w" "~n Varbinds: ~w", [Sz, MibView, Varbinds]), - case do_get_next(MibView, Varbinds) of + case do_get_next(MibView, Varbinds, GbMaxVBs) of {noError, 0, UNextVarbinds} -> ?vt("try_get_bulk -> noError: " "~n UNextVarbinds: ~p", [UNextVarbinds]), - NextVarbinds = lists:keysort(#varbind.org_index, UNextVarbinds), + NextVarbinds = org_index_sort_vbs(UNextVarbinds), case (catch enc_vbs(Sz, NextVarbinds)) of {error, Idx, Reason} -> user_err("failed encoding varbind ~w:~n~p", [Idx, Reason]), @@ -3547,9 +3770,8 @@ get_err({ErrC, ErrI, Vbs}) -> {get_err_i(ErrC), ErrI, Vbs}. get_err_i(noError) -> noError; -get_err_i(S) -> - ?vtrace("convert '~p' to 'genErr'",[S]), - genErr. +get_err_i(tooBig) -> tooBig; % OTP-9700 +get_err_i(ES) -> ?vtrace("convert ErrorStatus '~p' to 'genErr'", [ES]), genErr. v2err_to_v1err(noError) -> noError; v2err_to_v1err(noAccess) -> noSuchName; @@ -4038,6 +4260,9 @@ get_multi_threaded(Opts) -> get_versions(Opts) -> get_option(versions, Opts, [v1,v2,v3]). +get_gb_max_vbs(Opts) -> + get_option(gb_max_vbs, Opts, infinity). + get_note_store_opt(Opts) -> get_option(note_store, Opts, []). diff --git a/lib/snmp/src/agent/snmpa_internal.hrl b/lib/snmp/src/agent/snmpa_internal.hrl index 9fa874f119..908bb97bd0 100644 --- a/lib/snmp/src/agent/snmpa_internal.hrl +++ b/lib/snmp/src/agent/snmpa_internal.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. +%% Copyright Ericsson AB 2006-2011. 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 @@ -24,6 +24,15 @@ -define(DEFAULT_LOCAL_ENGINE_ID, snmp_framework_mib:get_engine_id()). +%% -- Max number of VBs in a Get-BULK response -- +%% (( The default value, 1000, is *way* more )) +%% (( then there is room for in a normal pdu )) +%% (( (unless the max pdu size has been )) +%% (( cranked way up), so this value should )) +%% (( suffice as "infinity" withou actually )) +%% (( causing memory issues for the VM ... )) +-define(DEFAULT_GB_MAX_VBS, 1000). + -define(snmpa_info(F, A), ?snmp_info("agent", F, A)). -define(snmpa_warning(F, A), ?snmp_warning("agent", F, A)). -define(snmpa_error(F, A), ?snmp_error("agent", F, A)). diff --git a/lib/snmp/src/agent/snmpa_supervisor.erl b/lib/snmp/src/agent/snmpa_supervisor.erl index 5ef5914e18..7a9c214e0d 100644 --- a/lib/snmp/src/agent/snmpa_supervisor.erl +++ b/lib/snmp/src/agent/snmpa_supervisor.erl @@ -176,8 +176,8 @@ init([AgentType, Opts]) -> "~n AgentType: ~p" "~n Opts: ~p", [AgentType, Opts]), - put(sname, asup), - put(verbosity,get_verbosity(Opts)), + put(sname, asup), + put(verbosity, get_verbosity(Opts)), ?vlog("starting",[]), @@ -203,7 +203,12 @@ init([AgentType, Opts]) -> Vsns = get_opt(versions, Opts, [v1,v2,v3]), ?vdebug("[agent table] store versions: ~p",[Vsns]), ets:insert(snmp_agent_table, {versions, Vsns}), - + + %% -- Max number of VBs in a Get-BULK response -- + GbMaxVBs = get_gb_max_vbs(Opts), + ?vdebug("[agent table] Get-BULK max VBs: ~p", [GbMaxVBs]), + ets:insert(snmp_agent_table, {gb_max_vbs, GbMaxVBs}), + %% -- DB-directory -- DbDir = get_opt(db_dir, Opts), ?vdebug("[agent table] store db_dir: ~n ~p",[DbDir]), @@ -377,7 +382,8 @@ init([AgentType, Opts]) -> {versions, Vsns}, {net_if, NiOpts}, {mib_server, MibsOpts}, - {note_store, NsOpts}| + {note_store, NsOpts}, + {gb_max_vbs, GbMaxVBs} | get_opt(master_agent_options, Opts, [])], AgentSpec = @@ -542,6 +548,32 @@ get_verbosity(Opts) -> get_agent_type(Opts) -> get_opt(agent_type, Opts, master). + +%% We validate this option! This should really be done for all +%% options, but it is beyond the scope of this ticket, OTP-9700. + +get_gb_max_vbs(Opts) -> + Validate = + fun(GbMaxVBs) + when ((is_integer(GbMaxVBs) andalso (GbMaxVBs > 0)) orelse + (GbMaxVBs =:= infinity)) -> + ok; + (_) -> + error + end, + get_option(gb_max_vbs, ?DEFAULT_GB_MAX_VBS, Validate, Opts). + +get_option(Key, Default, Validate, Opts) + when is_list(Opts) andalso is_function(Validate) -> + Value = get_opt(Key, Opts, Default), + case Validate(Value) of + ok -> + Value; + error -> + exit({bad_option, Key, Value}) + end. + + get_opt(Key, Opts) -> snmp_misc:get_option(Key, Opts). -- cgit v1.2.3 From 44afbca7de2d14993df33d5329a9699a588ff6b0 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 2 Dec 2011 18:41:34 +0100 Subject: [snmp] Fixed the mt_trap test-case It has long been broken, but this fact was hidden by the faulty expect functions. OTP-9700 --- lib/snmp/test/snmp_agent_test.erl | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl index 9d2e9969c4..3af55bc002 100644 --- a/lib/snmp/test/snmp_agent_test.erl +++ b/lib/snmp/test/snmp_agent_test.erl @@ -1200,7 +1200,10 @@ test_multi_threaded(suite) -> {req, [], {conf, init_mt, mt_cases(), finish_mt}}. mt_cases() -> - [multi_threaded, mt_trap]. + [ + multi_threaded, + mt_trap + ]. init_mt(Config) when is_list(Config) -> SaNode = ?config(snmp_sa, Config), @@ -3024,8 +3027,9 @@ mt_trap_test(MA) -> ?DBG("mt_trap_test(01) -> issue testTrapv22 (standard trap)", []), snmpa:send_trap(MA, testTrapv22, "standard trap"), ?DBG("mt_trap_test(02) -> await v2trap", []), - ?line expect(1, v2trap, [{[sysUpTime, 0], any}, - {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?line expect(mt_trap_test_1, v2trap, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), ?DBG("mt_trap_test(03) -> issue mtTrap (standard trap)", []), snmpa:send_trap(MA, mtTrap, "standard trap"), @@ -3033,28 +3037,22 @@ mt_trap_test(MA) -> ?DBG("mt_trap_test(04) -> multi pid: ~p. Now request sysUpTime...", [Pid]), g([[sysUpTime,0]]), - %% Previously (before OTP-6784) this was done at 09 below - %% when the test1:multiStr was actually executed by the - %% worker-process, but as of 4.9.4, this is now executed - %% my the master_agent-process... - ?DBG("mt_trap_test(05) -> send continue to multi-pid", []), - Pid ! continue, - ?DBG("mt_trap_test(06) -> await sysUpTime", []), - ?line expect(2, [{[sysUpTime,0], any}]), + ?line expect(mt_trap_test_2, [{[sysUpTime,0], any}]), ?DBG("mt_trap_test(07) -> issue testTrapv22 (standard trap)", []), snmpa:send_trap(MA, testTrapv22, "standard trap"), ?DBG("mt_trap_test(08) -> await v2trap", []), - ?line expect(3, v2trap, [{[sysUpTime, 0], any}, - {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?line expect(mt_trap_test_3, v2trap, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), - %% ?DBG("mt_trap_test(09) -> send continue to multi-pid", []), - %% Pid ! continue, + ?DBG("mt_trap_test(09) -> send continue to multi-pid", []), + Pid ! continue, ?DBG("mt_trap_test(10) -> await v2trap", []), - ?line expect(4, v2trap, [{[sysUpTime, 0], any}, - {[snmpTrapOID, 0], ?testTrap ++ [2]}, - {[multiStr,0], "ok"}]), + ?line expect(mt_trap_test_4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [2]}, + {[multiStr,0], "ok"}]), ?DBG("mt_trap_test(11) -> done", []), ok. -- cgit v1.2.3 From 558f3c606b2cbdf46ecb53de48387ebb93527c07 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 5 Dec 2011 12:53:25 +0100 Subject: [snmp] Add a more informative return value when the trap sending fails OTP-9700 --- lib/snmp/src/agent/snmpa_trap.erl | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/snmp/src/agent/snmpa_trap.erl b/lib/snmp/src/agent/snmpa_trap.erl index 450cb2e9f4..3b31c8d909 100644 --- a/lib/snmp/src/agent/snmpa_trap.erl +++ b/lib/snmp/src/agent/snmpa_trap.erl @@ -339,9 +339,25 @@ send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, NetIf) -> send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, NetIf). +%% The agent normally does not care about the result, +%% but since it can be usefull when debugging, add +%% some info when we fail to send the trap(s). send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, NetIf) -> - (catch do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, - LocalEngineID, NetIf)). + try + begin + do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID, NetIf) + end + catch + T:E -> + Info = [{args, [TrapRec, NotifyName, ContextName, + Recv, Vbs, LocalEngineID, NetIf]}, + {tag, T}, + {err, E}, + {stacktrace, erlang:get_stacktrace()}], + {error, {failed_sending_trap, Info}} + end. + do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, NetIf) -> -- cgit v1.2.3 From c4a1020847a7d08be9696bb41a666e36cdf4206c Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 5 Dec 2011 14:40:21 +0100 Subject: [snmp] Be more verbose in the worker procs Add a verbosity printout for results of the requests sent to it). Also fixed handling sent_trap and appup. OTP-9700 --- lib/snmp/src/agent/snmpa_agent.erl | 206 +++++++++++++++++++--------------- lib/snmp/src/agent/snmpa_internal.hrl | 4 +- lib/snmp/src/app/snmp.appup.src | 52 ++++++--- 3 files changed, 156 insertions(+), 106 deletions(-) diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index 95199065b3..0510d7b625 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -115,7 +115,7 @@ {extra, Extra}]}. -define(mk_send_trap_wreq(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID), - #wrequest{cmd = handle_pdu, + #wrequest{cmd = send_trap, info = [{trap_rec, TrapRec}, {notify_name, NotifyName}, {context_name, ContextName}, @@ -1656,92 +1656,119 @@ worker(Master, Dict) -> worker_loop(Master). worker_loop(Master) -> - receive - #wrequest{cmd = handle_pdu, - info = Info} -> - ?vtrace("worker_loop -> received handle_pdu request", []), - Vsn = proplists:get_value(vsn, Info), - Pdu = proplists:get_value(pdu, Info), - PduMS = proplists:get_value(pdu_ms, Info), - ACMData = proplists:get_value(acm_data, Info), - Address = proplists:get_value(addr, Info), - GbMaxVBs = proplists:get_value(gb_max_vbs, Info), - Extra = proplists:get_value(extra, Info), - handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra), - ok; - - - #wrequest{cmd = send_trap, - info = Info} -> - ?vtrace("worker_loop -> send trap", []), - TrapRec = proplists:get_value(trap_rec, Info), - NotifyName = proplists:get_value(notify_name, Info), - ContextName = proplists:get_value(context_name, Info), - Recv = proplists:get_value(receiver, Info), - Vbs = proplists:get_value(vbs, Info), - LocalEngineID = proplists:get_value(local_engine_id, Info), - snmpa_trap:send_trap(TrapRec, NotifyName, - ContextName, Recv, Vbs, LocalEngineID, - get(net_if)), - ok; - - - #wrequest{cmd = verbosity, - info = Info} -> - Verbosity = proplists:get_value(verbosity, Info), - put(verbosity, snmp_verbosity:validate(Verbosity)), - ok; - - - #wrequest{cmd = terminate} -> - exit(normal); - - - %% ************************************************************* - %% - %% Kept for backward compatibillity reasons - %% - %% ************************************************************* - - {Vsn, Pdu, PduMS, ACMData, Address, Extra} -> - ?vtrace("worker_loop -> received request", []), - handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, - ?DEFAULT_GB_MAX_VBS, Extra), - Master ! worker_available; - - %% We don't trap exits! - {TrapRec, NotifyName, ContextName, Recv, Vbs} -> - ?vtrace("worker_loop -> send trap:" - "~n ~p", [TrapRec]), - snmpa_trap:send_trap(TrapRec, NotifyName, - ContextName, Recv, Vbs, get(net_if)), - Master ! worker_available; - - %% We don't trap exits! - {send_trap, - TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID} -> - ?vtrace("worker_loop -> send trap:" - "~n ~p", [TrapRec]), - snmpa_trap:send_trap(TrapRec, NotifyName, - ContextName, Recv, Vbs, LocalEngineID, - get(net_if)), - Master ! worker_available; - - {verbosity, Verbosity} -> - put(verbosity,snmp_verbosity:validate(Verbosity)); - - terminate -> - exit(normal); - - _X -> - %% ignore - ok - - after 30000 -> - %% This is to assure that the worker process leaves a - %% possibly old version of this module. - ok - end, + Res = + receive + #wrequest{cmd = handle_pdu, + info = Info} = Req -> + ?vtrace("worker_loop -> received handle_pdu request with" + "~n Info: ~p", [Info]), + Vsn = proplists:get_value(vsn, Info), + Pdu = proplists:get_value(pdu, Info), + PduMS = proplists:get_value(pdu_ms, Info), + ACMData = proplists:get_value(acm_data, Info), + Address = proplists:get_value(addr, Info), + GbMaxVBs = proplists:get_value(gb_max_vbs, Info), + Extra = proplists:get_value(extra, Info), + HandlePduRes = + try + begin + handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, + GbMaxVBs, Extra) + end + catch + T:E -> + exit({worker_crash, Req, T, E, + erlang:get_stacktrace()}) + end, + Master ! worker_available, + HandlePduRes; % For debugging... + + + #wrequest{cmd = send_trap, + info = Info} = Req -> + ?vtrace("worker_loop -> received send_trap request with" + "~n Info: ~p", [Info]), + TrapRec = proplists:get_value(trap_rec, Info), + NotifyName = proplists:get_value(notify_name, Info), + ContextName = proplists:get_value(context_name, Info), + Recv = proplists:get_value(receiver, Info), + Vbs = proplists:get_value(varbinds, Info), + LocalEngineID = proplists:get_value(local_engine_id, Info), + SendTrapRes = + try + begin + snmpa_trap:send_trap(TrapRec, NotifyName, + ContextName, Recv, Vbs, + LocalEngineID, + get(net_if)) + end + catch + T:E -> + exit({worker_crash, Req, T, E, + erlang:get_stacktrace()}) + end, + Master ! worker_available, + SendTrapRes; % For debugging... + + + #wrequest{cmd = verbosity, + info = Info} -> + Verbosity = proplists:get_value(verbosity, Info), + put(verbosity, snmp_verbosity:validate(Verbosity)); + + + #wrequest{cmd = terminate} -> + ?vtrace("worker_loop -> received terminate request", []), + exit(normal); + + + %% ************************************************************* + %% + %% Kept for backward compatibillity reasons + %% + %% ************************************************************* + + {Vsn, Pdu, PduMS, ACMData, Address, Extra} -> + ?vtrace("worker_loop -> received request", []), + handle_pdu2(Vsn, Pdu, PduMS, ACMData, Address, + ?DEFAULT_GB_MAX_VBS, Extra), + Master ! worker_available; + + %% We don't trap exits! + {TrapRec, NotifyName, ContextName, Recv, Vbs} -> + ?vtrace("worker_loop -> send trap:" + "~n ~p", [TrapRec]), + snmpa_trap:send_trap(TrapRec, NotifyName, + ContextName, Recv, Vbs, get(net_if)), + Master ! worker_available; + + %% We don't trap exits! + {send_trap, + TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID} -> + ?vtrace("worker_loop -> send trap:" + "~n ~p", [TrapRec]), + snmpa_trap:send_trap(TrapRec, NotifyName, + ContextName, Recv, Vbs, LocalEngineID, + get(net_if)), + Master ! worker_available; + + {verbosity, Verbosity} -> + put(verbosity, snmp_verbosity:validate(Verbosity)); + + terminate -> + exit(normal); + + _X -> + %% ignore + ignore_unknown + + after 30000 -> + %% This is to assure that the worker process leaves a + %% possibly old version of this module. + ok + end, + ?vtrace("worker_loop -> wrap with" + "~n ~p", [Res]), ?MODULE:worker_loop(Master). @@ -1756,11 +1783,10 @@ handle_snmp_pdu(true, Vsn, Pdu, PduMS, ACMData, Address, Extra, S; handle_snmp_pdu(true, Vsn, #pdu{type = 'set-request'} = Pdu, PduMS, ACMData, Address, Extra, - #state{set_worker = Worker, - gb_max_vbs = GbMaxVBs} = S) -> + #state{set_worker = Worker} = S) -> ?vtrace("handle_snmp_pdu -> multi-thread agent: " "send set-request to main worker",[]), - WRequest = ?mk_pdu_wreq(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra), + WRequest = ?mk_pdu_wreq(Vsn, Pdu, PduMS, ACMData, Address, infinity, Extra), Worker ! WRequest, S#state{worker_state = busy}; handle_snmp_pdu(true, Vsn, Pdu, PduMS, diff --git a/lib/snmp/src/agent/snmpa_internal.hrl b/lib/snmp/src/agent/snmpa_internal.hrl index 908bb97bd0..671a3e4aaf 100644 --- a/lib/snmp/src/agent/snmpa_internal.hrl +++ b/lib/snmp/src/agent/snmpa_internal.hrl @@ -29,9 +29,9 @@ %% (( then there is room for in a normal pdu )) %% (( (unless the max pdu size has been )) %% (( cranked way up), so this value should )) -%% (( suffice as "infinity" withou actually )) +%% (( suffice as "infinity" without actually )) %% (( causing memory issues for the VM ... )) --define(DEFAULT_GB_MAX_VBS, 1000). +-define(DEFAULT_GB_MAX_VBS, 1000). -define(snmpa_info(F, A), ?snmp_info("agent", F, A)). -define(snmpa_warning(F, A), ?snmp_warning("agent", F, A)). diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 14f413099b..383b91b2f8 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -26,55 +26,64 @@ [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.17.1", [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, - {update, snmpm_server, soft, soft_purge, soft_purge, []} + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.17", [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, - {update, snmpm_server, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpm_server, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.16.2", [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmp_log, soft_purge, soft_purge, []}, {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, {load_module, snmpm_mpd, soft_purge, soft_purge, []}, - {update, snmpm_server, soft, soft_purge, soft_purge, []} + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.16.1", [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmp_log, soft_purge, soft_purge, []}, @@ -85,6 +94,7 @@ {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, @@ -97,6 +107,7 @@ [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmp_log, soft_purge, soft_purge, []}, @@ -108,6 +119,7 @@ {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, @@ -126,37 +138,44 @@ [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []} ] }, {"4.17.1", [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, - {update, snmpm_server, soft, soft_purge, soft_purge, []} + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.17", [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, - {update, snmpm_server, soft, soft_purge, soft_purge, []} + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.16.2", [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmp_log, soft_purge, soft_purge, []}, @@ -164,18 +183,20 @@ {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, {load_module, snmpm_mpd, soft_purge, soft_purge, []}, - {update, snmpm_server, soft, soft_purge, soft_purge, []} + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.16.1", [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmp_log, soft_purge, soft_purge, []}, @@ -186,6 +207,7 @@ {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, @@ -198,6 +220,7 @@ [ {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, + {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmp_log, soft_purge, soft_purge, []}, @@ -209,6 +232,7 @@ {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, -- cgit v1.2.3 From a1c84a9eb253f8b7aa5cdc8b88ca17691ed52c14 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 14 Dec 2011 14:15:05 +0100 Subject: [snmp] Updated doc and fixed wrequest create macros Release notes updated, together with documentation of the new config option. Also fixed the wrequest create macros (forgot end parantesis). OTP-9700 --- lib/snmp/doc/src/notes.xml | 58 ++++++++++++++++++++ lib/snmp/doc/src/snmp_app.xml | 109 +++++++++++++++++++++++++++++++++++-- lib/snmp/doc/src/snmp_config.xml | 108 ++++++++++++++++++++++++++++++++---- lib/snmp/src/agent/snmpa_agent.erl | 6 +- 4 files changed, 263 insertions(+), 18 deletions(-) diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 1e31d72a2c..8d9de1d70b 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -32,6 +32,64 @@ notes.xml +
+ SNMP Development Toolkit 4.17.3 + +

Version 4.17.3 supports code replacement in runtime from/to + version 4.17.2, 4.17.1, 4.17, 4.16.2, 4.16.1 and 4.16.

+ +
+ Improvements and new features + + + + +

[agent] DoS attack using GET-BULK with large value of + MaxRepetitions. + A preventive method has been implementing by simply + limit the number of varbinds that can be included in + a Get-BULK response message. This is specified by the + new config option, + gb_max_vbs. +

+

Own Id: OTP-9700

+
+ +
+ +
+ +
+ Reported Fixed Bugs and Malfunctions +

-

+ + + +
+ +
+ Incompatibilities +

-

+
+ +
+ +
SNMP Development Toolkit 4.17.2 diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml index 694e619da1..f6abe783b3 100644 --- a/lib/snmp/doc/src/snmp_app.xml +++ b/lib/snmp/doc/src/snmp_app.xml @@ -1,10 +1,10 @@ - +
- 19972010 + 19972011 Ericsson AB. All Rights Reserved. @@ -78,7 +78,15 @@ ]. - + + +

Each snmp component has its own set of configuration parameters, even though some of the types are common to both components.

@@ -92,6 +100,7 @@ {agent_verbosity, verbosity()} | {discovery, agent_discovery()} | {versions, versions()} | + {gb_max_vbs, gb_max_vbs()} | {priority, priority()} | {multi_threaded, multi_threaded()} | {db_dir, db_dir()} | @@ -122,8 +131,10 @@ {def_user_data, def_user_data()} +

Agent specific config options and types:

+ ]]>

If master, one master agent is @@ -131,6 +142,7 @@

Default is master.

+ ]]>

agent_discovery_opt() = @@ -143,6 +155,7 @@

For defaults see the options in agent_discovery_opt().

+ ]]>

agent_terminating_discovery_opt() = @@ -160,6 +173,7 @@ + ]]>

agent_originating_discovery_opt() = @@ -173,6 +187,7 @@ + ]]>

If true, the agent is multi-threaded, with one @@ -180,11 +195,21 @@

Default is false.

+ ]]>

Defines where the SNMP agent internal db files are stored.

+ + ]]> + +

Defines the maximum number of varbinds allowed + in a Get-BULK response.

+

Default is 1000.

+
+ + ]]>

local_db_opt() = {repair, agent_repair()} | {auto_save, agent_auto_save()} | {verbosity, verbosity()}

@@ -192,6 +217,7 @@

For defaults see the options in local_db_opt().

+ ]]>

When starting snmpa_local_db it always tries to open an @@ -202,6 +228,7 @@

Default is true.

+ ]]>

The auto save interval. The table is flushed to disk @@ -209,6 +236,7 @@

Default is 5000.

+ ]]>

agent_net_if_opt() = {module, agent_net_if_module()} | {verbosity, verbosity()} | {options, agent_net_if_options()}

@@ -217,6 +245,7 @@

For defaults see the options in agent_net_if_opt().

+ ]]>

Module which handles the network interface part for the @@ -225,6 +254,7 @@

Default is snmpa_net_if.

+ ]]>

agent_net_if_option() = {bind_to, bind_to()} | @@ -239,12 +269,14 @@

For defaults see the options in agent_net_if_option().

+ ]]>

Max number of simultaneous requests handled by the agent.

Default is infinity.

+ ]]>

agent_net_if_filter_option() = {module, agent_net_if_filter_module()}

@@ -255,6 +287,7 @@ agent_net_if_filter_option().

+ ]]>

Module which handles the network interface filter part for the @@ -263,6 +296,7 @@

Default is snmpa_net_if_filter.

+ ]]>

Specifies a list of MIBs (including path) that defines which MIBs @@ -277,6 +311,7 @@

Default is [].

+ ]]>

Specifies how info retrieved from the mibs will be stored.

@@ -302,6 +337,7 @@ mnesia/dets table already exist.

+ ]]>

mib_server_opt() = {mibentry_override, mibentry_override()} | {trapentry_override, trapentry_override()} | {verbosity, verbosity()} | {cache, mibs_cache()}

@@ -309,6 +345,7 @@

For defaults see the options in mib_server_opt().

+ ]]>

If this value is false, then when loading a mib each mib- @@ -318,6 +355,7 @@

Default is false.

+ ]]>

If this value is false, then when loading a mib each trap @@ -327,6 +365,7 @@

Default is false.

+ ]]>

Shall the agent utilize the mib server lookup cache or not.

@@ -334,6 +373,7 @@ default values apply).

+ ]]>

mibs_cache_opt() = {autogc, mibs_cache_autogc()} | {gclimit, mibs_cache_gclimit()} | {age, mibs_cache_age()}

@@ -341,6 +381,7 @@

For defaults see the options in mibs_cache_opt().

+ ]]>

Defines if the mib server shall perform cache gc automatically or @@ -349,6 +390,7 @@

Default is true.

+ 0 ]]>

Defines how old the entries in the cache will be allowed before @@ -358,6 +400,7 @@

Default is 10 timutes.

+ 0 | infinity ]]>

When performing a GC, this is the max number of cache entries @@ -368,6 +411,7 @@

Default is 100.

+ ]]>

Defines an error report module, implementing the @@ -377,6 +421,7 @@

Default is snmpa_error_logger.

+ symbolic_store() = [symbolic_store_opt()]

symbolic_store_opt() = {verbosity, verbosity()}

@@ -384,23 +429,29 @@

For defaults see the options in symbolic_store_opt().

+ target_cache() = [target_cache_opt()]

target_cache_opt() = {verbosity, verbosity()}

Defines options specific for the SNMP agent target cache.

For defaults see the options in target_cache_opt().

+ + ]]>

agent_config_opt() = {dir, agent_config_dir()} | {force_load, force_load()} | {verbosity, verbosity()}

Defines specific config related options for the SNMP agent.

For defaults see the options in agent_config_opt().

+ + ]]>

Defines where the SNMP agent configuration files are stored.

+ ]]>

If true the configuration files are re-read @@ -412,14 +463,18 @@ +

Manager specific config options and types:

+ ]]>

server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}

Specifies the options for the manager server process.

Default is silence.

+ + ]]>

Asynchroneous request cleanup time. For every requests, @@ -440,6 +495,7 @@

Default is 30000.

+ ]]>

manager_config_opt() = {dir, manager_config_dir()} | {db_dir, manager_db_dir()} | {db_init_error, db_init_error()} | {repair, manager_repair()} | {auto_save, manager_auto_save()} | {verbosity, verbosity()}

@@ -447,16 +503,19 @@

For defaults see the options in manager_config_opt().

+ ]]>

Defines where the SNMP manager configuration files are stored.

+ ]]>

Defines where the SNMP manager store persistent data.

+ ]]>

Defines the repair option for the persistent database (if @@ -464,6 +523,7 @@

Default is true.

+ ]]>

The auto save interval. The table is flushed to disk @@ -471,6 +531,7 @@

Default is 5000.

+ ]]>

This option defines how the manager will handle the sending of @@ -500,6 +561,7 @@

Default is auto.

+ ]]>

Specifies a list of MIBs (including path) and defines which MIBs @@ -507,6 +569,7 @@

Default is [].

+ ]]>

manager_net_if_opt() = {module, manager_net_if_module()} | @@ -517,6 +580,7 @@

For defaults see the options in manager_net_if_opt().

+ ]]>

manager_net_if_option() = {bind_to, bind_to()} | @@ -530,6 +594,7 @@

For defaults see the options in manager_net_if_option().

+ ]]>

Module which handles the network interface part for the @@ -538,6 +603,7 @@

Default is snmpm_net_if.

+ ]]>

manager_net_if_filter_option() = {module, manager_net_if_filter_module()}

@@ -548,6 +614,7 @@ manager_net_if_filter_option().

+ ]]>

Module which handles the network interface filter part for the @@ -556,6 +623,7 @@

Default is snmpm_net_if_filter.

+ ]]>

The module implementing the default user. See the @@ -563,6 +631,7 @@

Default is snmpm_user_default.

+ ]]>

Data for the default user. Passed to the user module when @@ -571,8 +640,10 @@ +

Common config types:

+ restart_type() = permanent | transient | temporary

See supervisor @@ -580,6 +651,8 @@

Default is permanent for the agent and transient for the manager.

+ + db_init_error() = terminate | create

Defines what to do if the agent or manager is unable to open an @@ -588,23 +661,31 @@ agent/manager will remove the faulty file(s) and create new ones.

Default is terminate.

+ + ]]>

Defines the Erlang priority for all SNMP processes.

Default is normal.

+ + ]]>

version() = v1 | v2 | v3

Which SNMP versions shall be accepted/used.

Default is [v1,v2,v3].

+ + ]]>

Verbosity for a SNMP process. This specifies now much debug info is printed.

Default is silence.

+ + ]]>

If true, net_if binds to the IP address. @@ -612,6 +693,8 @@ where it is running.

Default is false.

+ + ]]>

If true, net_if does not specify that the IP @@ -619,22 +702,30 @@ the address is set to reusable.

Default is false.

+ + ]]>

Receive buffer size.

Default value is defined by gen_udp.

+ + ]]>

Send buffer size.

Default value is defined by gen_udp.

+ + ]]>

note_store_opt() = {timeout, note_store_timeout()} | {verbosity, verbosity()}

Specifies the start-up verbosity for the SNMP note store.

For defaults see the options in note_store_opt().

+ + ]]>

Note cleanup time. When storing a note in the note store, @@ -643,9 +734,9 @@ milli-seconds.

Default is 30000.

-
+ ]]>

audit_trail_log_opt() = {type, atl_type()} | {dir, atl_dir()} | {size, atl_size()} | {repair, atl_repair()} | {seqno, atl_seqno()}

@@ -655,6 +746,8 @@ size options are mandatory.

If not present, audit trail logging is not used.

+ + ]]>

Specifies what type of an audit trail log should be used. @@ -675,12 +768,16 @@

Default is read_write.

+ + ]]>

Specifies where the audit trail log should be stored.

If audit_trail_log specifies that logging should take place, this parameter must be defined.

+ + ]]>

Specifies the size of the audit @@ -688,6 +785,8 @@

If audit_trail_log specifies that logging should take place, this parameter must be defined.

+ + ]]>

Specifies if and how the audit trail log shall be repaired @@ -699,6 +798,8 @@ analysis.

Default is true.

+ + ]]>

Specifies if the audit trail log entries will be (sequence) diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml index 769b908adc..ab66a11387 100644 --- a/lib/snmp/doc/src/snmp_config.xml +++ b/lib/snmp/doc/src/snmp_config.xml @@ -1,10 +1,10 @@ - +

- 19972010 + 19972011 Ericsson AB. All Rights Reserved. @@ -40,6 +40,7 @@ starting the application (agent and/or manager) debugging the application (agent and/or manager) +

Refer also to the chapter(s) Definition of Agent Configuration Files and Definition of Manager Configuration Files which contains more detailed information @@ -73,7 +74,14 @@ - + +

The agent and manager uses (application) configuration parameters to find out where these directories are located. The parameters should be @@ -87,6 +95,7 @@ {agent_verbosity, verbosity()} | {versions, versions()} | {discovery, agent_discovery()} | + {gb_max_vbs, gb_max_vbs()} | {priority, priority()} | {multi_threaded, multi_threaded()} | {db_dir, db_dir()} | @@ -117,8 +126,10 @@ {def_user_data, def_user_data()} +

Agent specific config options and types:

+ ]]>

If master, one master agent is @@ -126,6 +137,7 @@

Default is master.

+ ]]>

agent_discovery_opt() = @@ -138,6 +150,7 @@

For defaults see the options in agent_discovery_opt().

+ ]]>

agent_terminating_discovery_opt() = @@ -155,6 +168,7 @@ + ]]>

agent_originating_discovery_opt() = @@ -168,6 +182,7 @@ + ]]>

If true, the agent is multi-threaded, with one @@ -175,11 +190,21 @@

Default is false.

+ ]]>

Defines where the SNMP agent internal db files are stored.

+ + ]]> + +

Defines the maximum number of varbinds allowed + in a Get-BULK response.

+

Default is 1000.

+
+ + ]]>

local_db_opt() = {repair, agent_repair()} | {auto_save, agent_auto_save()} | {verbosity, verbosity()}

@@ -187,6 +212,7 @@

For defaults see the options in local_db_opt().

+ ]]>

When starting snmpa_local_db it always tries to open an @@ -197,6 +223,7 @@

Default is true.

+ ]]>

The auto save interval. The table is flushed to disk @@ -204,6 +231,7 @@

Default is 5000.

+ ]]>

agent_net_if_option() = {module, agent_net_if_module()} | @@ -214,6 +242,7 @@

For defaults see the options in agent_net_if_opt().

+ ]]>

Module which handles the network interface part for the @@ -222,6 +251,7 @@

Default is snmpa_net_if.

+ ]]>

agent_net_if_option() = {bind_to, bind_to()} | @@ -236,6 +266,14 @@

For defaults see the options in agent_net_if_option().

+ + ]]> + +

Max number of simultaneous requests handled by the agent.

+

Default is infinity.

+
+ + ]]>

@@ -245,6 +283,7 @@

For defaults see the options in agent_net_if_filter_option().

+ ]]>

Module which handles the network interface filter part for the @@ -254,12 +293,7 @@

Default is snmpa_net_if_filter.

- ]]> - -

Max number of simultaneous requests handled by the agent.

-

Default is infinity.

-
- + ]]>

Specifies a list of MIBs (including path) that defines which MIBs @@ -274,6 +308,7 @@

Default is [].

+ ]]>

Specifies how info retrieved from the mibs will be stored.

@@ -299,6 +334,7 @@ mnesia/dets table already exist.

+ ]]>

mib_server_opt() = {mibentry_override, mibentry_override()} | {trapentry_override, trapentry_override()} | {verbosity, verbosity()} | {cache, mibs_cache()}

@@ -306,6 +342,7 @@

For defaults see the options in mib_server_opt().

+ ]]>

If this value is false, then when loading a mib each mib- @@ -315,6 +352,7 @@

Default is false.

+ ]]>

If this value is false, then when loading a mib each trap @@ -324,6 +362,7 @@

Default is false.

+ ]]>

Shall the agent utilize the mib server lookup cache or not.

@@ -331,6 +370,7 @@ default values apply).

+ ]]>

mibs_cache_opt() = {autogc, mibs_cache_autogc()} | {gclimit, mibs_cache_gclimit()} | {age, mibs_cache_age()}

@@ -338,6 +378,7 @@

For defaults see the options in mibs_cache_opt().

+ ]]>

Defines if the mib server shall perform cache gc automatically or @@ -346,6 +387,7 @@

Default is true.

+ 0 ]]>

Defines how old the entries in the cache will be allowed before @@ -355,6 +397,7 @@

Default is 10 timutes.

+ 0 | infinity ]]>

When performing a GC, this is the max number of cache entries @@ -365,6 +408,7 @@

Default is 100.

+ ]]>

Defines an error report module, implementing the @@ -374,6 +418,7 @@

Default is snmpa_error_logger.

+ symbolic_store() = [symbolic_store_opt()]

symbolic_store_opt() = {verbosity, verbosity()}

@@ -381,12 +426,15 @@

For defaults see the options in symbolic_store_opt().

+ target_cache() = [target_cache_opt()]

target_cache_opt() = {verbosity, verbosity()}

Defines options specific for the SNMP agent target cache.

For defaults see the options in target_cache_opt().

+ + ]]>

agent_config_opt() = {dir, agent_config_dir()} | {force_load, force_load()} | {verbosity, verbosity()}

@@ -394,11 +442,13 @@

For defaults see the options in agent_config_opt().

+ ]]>

Defines where the SNMP agent configuration files are stored.

+ ]]>

If true the configuration files are re-read @@ -410,14 +460,18 @@ +

Manager specific config options and types:

+ ]]>

server_opt() = {timeout, server_timeout()} | {verbosity, verbosity()}

Specifies the options for the manager server process.

Default is silence.

+ + ]]>

Asynchroneous request cleanup time. For every requests, @@ -438,6 +492,7 @@

Default is 30000.

+ ]]>

manager_config_opt() = {dir, manager_config_dir()} | {db_dir, manager_db_dir()} | {db_init_error, db_init_error()} | {repair, manager_repair()} | {auto_save, manager_auto_save()} | {verbosity, verbosity()}

@@ -445,16 +500,19 @@

For defaults see the options in manager_config_opt().

+ ]]>

Defines where the SNMP manager configuration files are stored.

+ ]]>

Defines where the SNMP manager store persistent data.

+ ]]>

Defines the repair option for the persistent database (if @@ -462,6 +520,7 @@

Default is true.

+ ]]>

The auto save interval. The table is flushed to disk @@ -469,6 +528,7 @@

Default is 5000.

+ ]]>

This option defines how the manager will handle the sending of @@ -498,6 +558,7 @@

Default is auto.

+ ]]>

Specifies a list of MIBs (including path) and defines which MIBs @@ -505,6 +566,7 @@

Default is [].

+ ]]>

manager_net_if_opt() = {module, manager_net_if_module()} | @@ -515,6 +577,7 @@

For defaults see the options in manager_net_if_opt().

+ ]]>

manager_net_if_option() = {bind_to, bind_to()} | @@ -528,6 +591,7 @@

For defaults see the options in manager_net_if_option().

+ ]]>

Module which handles the network interface part for the @@ -536,6 +600,7 @@

Default is snmpm_net_if.

+ ]]>

manager_net_if_filter_option() = {module, manager_net_if_filter_module()}

@@ -546,6 +611,7 @@ manager_net_if_filter_option().

+ ]]>

Module which handles the network interface filter part for the @@ -554,6 +620,7 @@

Default is snmpm_net_if_filter.

+ ]]>

The module implementing the default user. See the @@ -561,6 +628,7 @@

Default is snmpm_user_default.

+ ]]>

Data for the default user. Passed to the user when calling @@ -569,8 +637,10 @@ +

Common config types:

+ restart_type() = permanent | transient | temporary

See supervisor @@ -579,6 +649,7 @@ for the manager.

+ db_init_error() = terminate | create

Defines what to do if the agent is unable to open an @@ -588,12 +659,14 @@

Default is terminate.

+ ]]>

Defines the Erlang priority for all SNMP processes.

Default is normal.

+ ]]>

version() = v1 | v2 | v3

@@ -601,6 +674,7 @@

Default is [v1,v2,v3].

+ ]]>

Verbosity for a SNMP process. This specifies now much debug info @@ -608,6 +682,7 @@

Default is silence.

+ ]]>

If true, net_if binds to the IP address. @@ -616,6 +691,7 @@

Default is false.

+ ]]>

If true, net_if does not specify that the IP @@ -624,17 +700,21 @@

Default is false.

+ ]]>

Receive buffer size.

Default value is defined by gen_udp.

+ + ]]>

Send buffer size.

Default value is defined by gen_udp.

+ ]]>

note_store_opt() = {timeout, note_store_timeout()} | {verbosity, verbosity()}

@@ -642,6 +722,7 @@

For defaults see the options in note_store_opt().

+ ]]>

Note cleanup time. When storing a note in the note store, @@ -649,10 +730,9 @@ process performs a GC to remove the expired note's. Time in milli-seconds.

Default is 30000.

- -
+ ]]>

audit_trail_log_opt() = {type, atl_type()} | {dir, atl_dir()} | {size, atl_size()} | {repair, atl_repair()} | {seqno, atl_seqno()}

@@ -663,6 +743,7 @@

If not present, audit trail logging is not used.

+ ]]>

Specifies what type of an audit trail log should be used. @@ -684,6 +765,7 @@

Default is read_write.

+ ]]>

Specifies where the audit trail log should be stored.

@@ -691,6 +773,7 @@ place, this parameter must be defined.

+ ]]>

Specifies the size of the audit @@ -699,6 +782,7 @@ take place, this parameter must be defined.

+ ]]>

Specifies if and how the audit trail log shall be repaired @@ -710,6 +794,8 @@ analysis.

Default is true.

+ + ]]>

Specifies if the audit trail log entries will be (sequence) diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index 0510d7b625..00fe9be098 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -112,7 +112,7 @@ {acm_data, ACMData}, {addr, Address}, {gb_max_vbs, GbMaxVBs}, - {extra, Extra}]}. + {extra, Extra}]}). -define(mk_send_trap_wreq(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID), #wrequest{cmd = send_trap, @@ -121,7 +121,7 @@ {context_name, ContextName}, {receiver, Recv}, {varbinds, Vbs}, - {local_engine_id, LocalEngineID}]}. + {local_engine_id, LocalEngineID}]}). -define(mk_terminate_wreq(), #wrequest{cmd = terminate, info = []}). -define(mk_verbosity_wreq(V), #wrequest{cmd = verbosity, info = [{verbosity, V}]}). @@ -3585,7 +3585,7 @@ conv_res([VbListOfBytes | T], Bytes) -> conv_res([], Bytes) -> Bytes. -%% The only only other value, then a positive integer, is infinity. +%% The only other value, then a positive integer, is infinity. do_get_rep(_Sz, _MibView, Count, Max, _, _Res, GbNumVBs, GbMaxVBs) when (is_integer(GbMaxVBs) andalso (GbNumVBs > GbMaxVBs)) -> ?vinfo("Max Get-BULK VBs limit (~w) exceeded (~w) when:" -- cgit v1.2.3 From dda02f0e90a72620745878e4834849029f3e616d Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 19 Jan 2012 17:48:53 +0100 Subject: [snmp/agent] Incorrect mib server cache gclimit update Mib server cache gclimit update function incorrectly calls age update function. The gclimit update function update_mibs_cache_gclimit/1 incorrectly called update_mibs_cache_age/2 update function. OTP-9868 --- lib/snmp/doc/src/notes.xml | 59 ++++++++++++++++++++++++++++++++++++++++- lib/snmp/src/agent/snmpa.erl | 4 +-- lib/snmp/src/app/snmp.appup.src | 16 ++++++++++- lib/snmp/vsn.mk | 8 +++--- 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 1e31d72a2c..9db372dbe1 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -4,7 +4,7 @@

- 19962011 + 19962012 Ericsson AB. All Rights Reserved. @@ -32,6 +32,63 @@ notes.xml
+
+ SNMP Development Toolkit 4.17.3 + +

Version 4.17.3 supports code replacement in runtime from/to + version 4.17.2, 4.17.1, 4.17, 4.16.2, 4.16.1 and 4.16.

+ +
+ Improvements and new features + + + + +

[agent] Mib server cache gclimit update function incorrectly calls + age update function. + The gclimit update function, + update_mibs_cache_gclimit/1, + incorrectly called the age update function, + update_mibs_cache_age/2.

+

Johan Claesson

+

Own Id: OTP-9868

+
+ +
+ +
+ +
+ Reported Fixed Bugs and Malfunctions +

-

+ + + +
+ +
+ Incompatibilities +

-

+
+ +
+ +
SNMP Development Toolkit 4.17.2 diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl index 87b191caed..5ff0883be3 100644 --- a/lib/snmp/src/agent/snmpa.erl +++ b/lib/snmp/src/agent/snmpa.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. 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 @@ -363,7 +363,7 @@ update_mibs_cache_age(Agent, Age) -> update_mibs_cache_gclimit(GcLimit) -> - update_mibs_cache_age(snmp_master_agent, GcLimit). + update_mibs_cache_gclimit(snmp_master_agent, GcLimit). update_mibs_cache_gclimit(Agent, GcLimit) -> snmpa_agent:update_mibs_cache_gclimit(Agent, GcLimit). diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index 6353fc979e..30f2075bc0 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. 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 @@ -22,14 +22,21 @@ %% ----- U p g r a d e ------------------------------------------------------- [ + {"4.17.2", + [ + {load_module, snmpa, soft_purge, soft_purge, []} + ] + }, {"4.17.1", [ + {load_module, snmpa, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.17", [ + {load_module, snmpa, soft_purge, soft_purge, []}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, {update, snmpm_server, soft, soft_purge, soft_purge, []} @@ -92,14 +99,21 @@ %% ------D o w n g r a d e --------------------------------------------------- [ + {"4.17.2", + [ + {load_module, snmpa, soft_purge, soft_purge, []} + ] + }, {"4.17.1", [ + {load_module, snmpa, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.17", [ + {load_module, snmpa, soft_purge, soft_purge, []}, {load_module, snmpa_net_if, soft_purge, soft_purge, []}, {load_module, snmpm, soft_purge, soft_purge, [snmpm_server]}, {update, snmpm_server, soft, soft_purge, soft_purge, []} diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index 39ec3dc7d4..9dd47a741c 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2011. All Rights Reserved. +# Copyright Ericsson AB 1997-2012. 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 @@ -17,11 +17,13 @@ # # %CopyrightEnd% -SNMP_VSN = 4.17.2 +SNMP_VSN = 4.17.3 PRE_VSN = APP_VSN = "snmp-$(SNMP_VSN)$(PRE_VSN)" -TICKETS = OTP-9236 +TICKETS = OTP-9868 + +TICKETS_4_17_2 = OTP-9236 TICKETS_4_17_1 = OTP-8761 -- cgit v1.2.3