diff options
Diffstat (limited to 'lib/snmp')
-rw-r--r-- | lib/snmp/doc/src/notes.xml | 70 | ||||
-rw-r--r-- | lib/snmp/doc/src/snmp_app.xml | 2 | ||||
-rw-r--r-- | lib/snmp/doc/src/snmp_config.xml | 2 | ||||
-rw-r--r-- | lib/snmp/doc/src/snmpa.xml | 36 | ||||
-rw-r--r-- | lib/snmp/doc/src/snmpa_mpd.xml | 42 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa.erl | 23 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_agent.erl | 230 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_internal.hrl | 12 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_mib.erl | 12 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_mpd.erl | 226 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_trap.erl | 95 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_usm.erl | 74 | ||||
-rw-r--r-- | lib/snmp/src/app/snmp.appup.src | 188 | ||||
-rw-r--r-- | lib/snmp/src/manager/snmpm_mpd.erl | 24 | ||||
-rw-r--r-- | lib/snmp/src/manager/snmpm_server.erl | 26 | ||||
-rw-r--r-- | lib/snmp/test/snmp_agent_test.erl | 49 | ||||
-rw-r--r-- | lib/snmp/test/snmp_agent_test_lib.erl | 12 | ||||
-rw-r--r-- | lib/snmp/test/snmp_manager_test.erl | 29 | ||||
-rw-r--r-- | lib/snmp/test/snmp_manager_user_test.erl | 43 | ||||
-rw-r--r-- | lib/snmp/test/snmp_test_lib.erl | 22 | ||||
-rw-r--r-- | lib/snmp/vsn.mk | 171 |
21 files changed, 920 insertions, 468 deletions
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index eb7c9db6ba..3f4954cfbd 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -33,6 +33,61 @@ </header> <section> + <title>SNMP Development Toolkit 4.17</title> + <p>Version 4.17 supports code replacement in runtime from/to + version 4.16.2, 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p> + + <section> + <title>Improvements and new features</title> + <!-- + <p>-</p> + --> + <list type="bulleted"> + <item> + <p>[agent] Added very basic support for multiple SNMPv3 + EngineIDs in a single agent. See + <seealso marker="snmpa#send_notification">send_notification/7</seealso>, + <seealso marker="snmpa_mpd#process_packet">process_packet/7</seealso>, + <seealso marker="snmpa_mpd#generate_response_msg">generate_response_msg/6</seealso> or + <seealso marker="snmpa_mpd#generate_msg">generate_msg/6</seealso> + for more info. </p> + + <p>Own Id: OTP-8478</p> + </item> + + </list> + + </section> + + <section> + <title>Reported Fixed Bugs and Malfunctions</title> + <p>-</p> + + <!-- + <list type="bulleted"> + <item> + <p>The config utility + (<seealso marker="snmp#config">snmp:config/0</seealso>) + generated a default notify.conf + with a bad name for the starndard trap entry (was "stadard trap", + but should have been "standard trap"). This has been corrected. </p> + <p>Kenji Rikitake</p> + <p>Own Id: OTP-8433</p> + </item> + + </list> + --> + + </section> + + <section> + <title>Incompatibilities</title> + <p>-</p> + </section> + </section> <!-- 4.17 --> + + + <section> <title>SNMP Development Toolkit 4.16.2</title> <p>Version 4.16.2 supports code replacement in runtime from/to version 4.16.1, 4.16, 4.15, 4.14 and 4.13.5.</p> @@ -60,6 +115,12 @@ <p>Own Id: OTP-8594</p> </item> + <item> + <p>Auto [agent] Changed default value for the MIB server cache. + GC is now on by default. </p> + <p>Own Id: OTP-8648</p> + </item> + </list> </section> @@ -83,6 +144,15 @@ <p>Own Id: OTP-8595</p> </item> + <item> + <p>[manager] Raise condition causing the manager server process to + crash. Unregistering an agent while traffic (set/get-operations) + is ongoing could cause a crash in the manager server process + (raise condition). </p> + <p>Own Id: OTP-8646</p> + <p>Aux Id: Seq 11585</p> + </item> + </list> </section> diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml index 57eb87a759..694e619da1 100644 --- a/lib/snmp/doc/src/snmp_app.xml +++ b/lib/snmp/doc/src/snmp_app.xml @@ -346,7 +346,7 @@ <p>Defines if the mib server shall perform cache gc automatically or leave it to the user (see <seealso marker="snmpa#gc_mibs_cache">gc_mibs_cache/0,1,2,3</seealso>). </p> - <p>Default is <c>false</c>.</p> + <p>Default is <c>true</c>.</p> </item> <tag><c><![CDATA[mibs_cache_age() = integer() > 0 <optional>]]></c></tag> diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml index 5bd36305fc..769b908adc 100644 --- a/lib/snmp/doc/src/snmp_config.xml +++ b/lib/snmp/doc/src/snmp_config.xml @@ -343,7 +343,7 @@ <p>Defines if the mib server shall perform cache gc automatically or leave it to the user (see <seealso marker="snmpa#gc_mibs_cache">gc_mibs_cache/0,1,2,3</seealso>). </p> - <p>Default is <c>false</c>.</p> + <p>Default is <c>true</c>.</p> </item> <tag><c><![CDATA[mibs_cache_age() = integer() > 0 <optional>]]></c></tag> diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml index b3661ae9b0..1be6abe6dd 100644 --- a/lib/snmp/doc/src/snmpa.xml +++ b/lib/snmp/doc/src/snmpa.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2004</year><year>2009</year> + <year>2004</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -13,12 +13,12 @@ compliance with the License. You should have received a copy of the Erlang Public License along with this software. If not, it can be retrieved online at http://www.erlang.org/. - + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - + </legalnotice> <title>snmpa</title> @@ -648,6 +648,20 @@ notification_delivery_info() = #snmpa_notification_delivery_info{} <desc> <p>Disable the mib server cache. </p> + <marker id="which_mibs_cache_size"></marker> + </desc> + </func> + + <func> + <name>which_mibs_cache_size() -> void()</name> + <name>which_mibs_cache_size(Agent) -> void()</name> + <fsummary>The size of the mib server cache</fsummary> + <type> + <v>Agent = pid() | atom()</v> + </type> + <desc> + <p>Retreive the size of the mib server cache. </p> + <marker id="gc_mibs_cache"></marker> </desc> </func> @@ -867,6 +881,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2). <name>send_notification(Agent, Notification, Receiver, Varbinds)</name> <name>send_notification(Agent, Notification, Receiver, NotifyName, Varbinds)</name> <name>send_notification(Agent, Notification, Receiver, NotifyName, ContextName, Varbinds) -> void() </name> + <name>send_notification(Agent, Notification, Receiver, NotifyName, ContextName, Varbinds, LocalEngineID) -> void() </name> <fsummary>Send a notification</fsummary> <type> <v>Agent = pid() | atom()</v> @@ -888,6 +903,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2). <v>OID = oid()</v> <v>Value = term()</v> <v>RowIndex = [int()]</v> + <v>LocalEngineID = string()</v> </type> <desc> <p>Sends the notification <c>Notification</c> to the @@ -1027,6 +1043,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2). <item><c>{?sysLocation_instance, "upstairs"}</c> (provided that the generated <c>.hrl</c> file is included)</item> </list> + <p>If a variable in the notification is a table element, the <c>RowIndex</c> for the element must be given in the <c>Varbinds</c> list. In this case, the OBJECT IDENTIFIER sent @@ -1034,15 +1051,27 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2). element. This OBJECT IDENTIFIER could be used in a get operation later. </p> + <p>This function is asynchronous, and does not return any information. If an error occurs, <c>user_err/2</c> of the error report module is called and the notification is discarded. </p> + <note> + <p>Note that the use of the LocalEngineID argument is only intended + for special cases, if the agent is to "emulate" multiple EngineIDs! + By default, the agent uses the value of <c>SnmpEngineID</c> + (see SNMP-FRAMEWORK-MIB). </p> + </note> + +<!-- <marker id="send_trap"></marker> +--> + <marker id="discovery"></marker> </desc> </func> +<!-- <func> <name>send_trap(Agent,Trap,Community)</name> <name>send_trap(Agent,Trap,Community,Varbinds) -> void()</name> @@ -1114,6 +1143,7 @@ snmp_agent:register_subagent(SA1,[1,2,3], SA2). <marker id="discovery"></marker> </desc> </func> +--> <func> <name>discovery(TargetName, Notification) -> {ok, ManagerEngineID} | {error, Reason}</name> diff --git a/lib/snmp/doc/src/snmpa_mpd.xml b/lib/snmp/doc/src/snmpa_mpd.xml index ea5bde8956..202e6b5661 100644 --- a/lib/snmp/doc/src/snmpa_mpd.xml +++ b/lib/snmp/doc/src/snmpa_mpd.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1999</year><year>2009</year> + <year>1999</year><year>2010</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -13,12 +13,12 @@ compliance with the License. You should have received a copy of the Erlang Public License along with this software. If not, it can be retrieved online at http://www.erlang.org/. - + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - + </legalnotice> <title>snmpa_mpd</title> @@ -63,15 +63,19 @@ </func> <func> - <name>process_packet(Packet, TDomain, TAddress, State) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket}</name> + <name>process_packet(Packet, TDomain, TAddress, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket}</name> + <name>process_packet(Packet, TDomain, TAddress, LocalEngineID, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket}</name> <fsummary>Process a packet received from the network</fsummary> <type> <v>Packet = binary()</v> <v>TDomain = snmpUDPDomain</v> <v>TAddress = {Ip, Udp}</v> + <v>LocalEngineID = string()</v> <v>Ip = {integer(), integer(), integer(), integer()}</v> <v>Udp = integer()</v> <v>State = mpd_state()</v> + <v>NoteStore = pid()</v> + <v>Log = snmp_log()</v> <v>Vsn = 'version-1' | 'version-2' | 'version-3'</v> <v>Pdu = #pdu</v> <v>PduMs = integer()</v> @@ -84,18 +88,27 @@ decryption as necessary. The return values should be passed the agent.</p> + <note> + <p>Note that the use of the LocalEngineID argument is only intended + for special cases, if the agent is to "emulate" multiple EngineIDs! + By default, the agent uses the value of <c>SnmpEngineID</c> + (see SNMP-FRAMEWORK-MIB). </p> + </note> + <marker id="generate_response_msg"></marker> </desc> </func> <func> - <name>generate_response_msg(Vsn, RePdu, Type, ACMData) -> {ok, Packet} | {discarded, Reason}</name> + <name>generate_response_msg(Vsn, RePdu, Type, ACMData, Log) -> {ok, Packet} | {discarded, Reason}</name> + <name>generate_response_msg(Vsn, RePdu, Type, ACMData, LocalEngineID, Log) -> {ok, Packet} | {discarded, Reason}</name> <fsummary>Generate a response packet to be sent to the network</fsummary> <type> <v>Vsn = 'version-1' | 'version-2' | 'version-3'</v> <v>RePdu = #pdu</v> <v>Type = atom()</v> <v>ACMData = acm_data()</v> + <v>LocalEngineID = string()</v> <v>Packet = binary()</v> </type> <desc> @@ -103,17 +116,27 @@ network. <c>Type</c> is the <c>#pdu.type</c> of the original request.</p> + <note> + <p>Note that the use of the LocalEngineID argument is only intended + for special cases, if the agent is to "emulate" multiple EngineIDs! + By default, the agent uses the value of <c>SnmpEngineID</c> + (see SNMP-FRAMEWORK-MIB). </p> + </note> + <marker id="generate_msg"></marker> </desc> </func> <func> - <name>generate_msg(Vsn, Pdu, MsgData, To) -> {ok, PacketsAndAddresses} | {discarded, Reason}</name> + <name>generate_msg(Vsn, NoteStore, Pdu, MsgData, To) -> {ok, PacketsAndAddresses} | {discarded, Reason}</name> + <name>generate_msg(Vsn, NoteStore, Pdu, MsgData, LocalEngineID, To) -> {ok, PacketsAndAddresses} | {discarded, Reason}</name> <fsummary>Generate a request message to be sent to the network</fsummary> <type> <v>Vsn = 'version-1' | 'version-2' | 'version-3'</v> + <v>NoteStore = pid()</v> <v>Pdu = #pdu</v> <v>MsgData = msg_data()</v> + <v>LocalEngineID = string()</v> <v>To = [dest_addrs()]</v> <v>PacketsAndAddresses = [{TDomain, TAddress, Packet}]</v> <v>TDomain = snmpUDPDomain</v> @@ -136,6 +159,13 @@ also received from the requests mentioned above. </p> + <note> + <p>Note that the use of the LocalEngineID argument is only intended + for special cases, if the agent is to "emulate" multiple EngineIDs! + By default, the agent uses the value of <c>SnmpEngineID</c> + (see SNMP-FRAMEWORK-MIB). </p> + </note> + <marker id="discarded_pdu"></marker> </desc> </func> diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl index a113bba3a7..87b191caed 100644 --- a/lib/snmp/src/agent/snmpa.erl +++ b/lib/snmp/src/agent/snmpa.erl @@ -47,6 +47,7 @@ mib_of/1, mib_of/2, me_of/1, me_of/2, invalidate_mibs_cache/0, invalidate_mibs_cache/1, + which_mibs_cache_size/0, which_mibs_cache_size/1, enable_mibs_cache/0, enable_mibs_cache/1, disable_mibs_cache/0, disable_mibs_cache/1, gc_mibs_cache/0, gc_mibs_cache/1, gc_mibs_cache/2, gc_mibs_cache/3, @@ -60,7 +61,7 @@ register_subagent/3, unregister_subagent/2, send_notification/3, send_notification/4, send_notification/5, - send_notification/6, + send_notification/6, send_notification/7, send_trap/3, send_trap/4, discovery/2, discovery/3, discovery/4, discovery/5, discovery/6, @@ -302,6 +303,13 @@ invalidate_mibs_cache(Agent) -> snmpa_agent:invalidate_mibs_cache(Agent). +which_mibs_cache_size() -> + which_mibs_cache_size(snmp_master_agent). + +which_mibs_cache_size(Agent) -> + snmpa_agent:which_mibs_cache_size(Agent). + + enable_mibs_cache() -> enable_mibs_cache(snmp_master_agent). @@ -415,14 +423,23 @@ send_notification(Agent, Notification, Recv, Varbinds) -> send_notification(Agent, Notification, Recv, NotifyName, Varbinds) -> send_notification(Agent, Notification, Recv, NotifyName, "", Varbinds). -send_notification(Agent, Notification, Recv, - NotifyName, ContextName, Varbinds) +send_notification(Agent, Notification, Recv, NotifyName, + ContextName, Varbinds) when (is_list(NotifyName) andalso is_list(ContextName) andalso is_list(Varbinds)) -> snmpa_agent:send_trap(Agent, Notification, NotifyName, ContextName, Recv, Varbinds). +send_notification(Agent, Notification, Recv, + NotifyName, ContextName, Varbinds, LocalEngineID) + when (is_list(NotifyName) andalso + is_list(ContextName) andalso + is_list(Varbinds) andalso + is_list(LocalEngineID)) -> + snmpa_agent:send_trap(Agent, Notification, NotifyName, + ContextName, Recv, Varbinds, LocalEngineID). + %% Kept for backwards compatibility send_trap(Agent, Trap, Community) -> send_notification(Agent, Trap, no_receiver, Community, "", []). diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index fb04fca632..f70885b2ec 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -30,7 +30,7 @@ -export([subagent_set/2, load_mibs/2, unload_mibs/2, which_mibs/1, whereis_mib/2, info/1, register_subagent/3, unregister_subagent/2, - send_trap/6, + send_trap/6, send_trap/7, register_notification_filter/5, unregister_notification_filter/2, which_notification_filter/1, @@ -48,6 +48,7 @@ get/2, get/3, get_next/2, get_next/3]). -export([mib_of/1, mib_of/2, me_of/1, me_of/2, invalidate_mibs_cache/1, + which_mibs_cache_size/1, enable_mibs_cache/1, disable_mibs_cache/1, gc_mibs_cache/1, gc_mibs_cache/2, gc_mibs_cache/3, enable_mibs_cache_autogc/1, disable_mibs_cache_autogc/1, @@ -64,7 +65,7 @@ %% 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/6]). + handle_pdu/7, worker/2, worker_loop/1, do_send_trap/7]). -ifndef(default_verbosity). -define(default_verbosity,silence). @@ -245,6 +246,10 @@ disable_mibs_cache(Agent) -> call(Agent, {mibs_cache_request, disable_cache}). +which_mibs_cache_size(Agent) -> + call(Agent, {mibs_cache_request, cache_size}). + + enable_mibs_cache_autogc(Agent) -> call(Agent, {mibs_cache_request, enable_autogc}). @@ -524,14 +529,15 @@ which_notification_filter(Agent) -> send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds) -> ?d("send_trap -> entry with" - "~n self(): ~p" - "~n Agent: ~p [~p]" - "~n Trap: ~p" - "~n NotifyName: ~p" - "~n CtxName: ~p" - "~n Recv: ~p" - "~n Varbinds: ~p", - [self(), Agent, wis(Agent), Trap, NotifyName, CtxName, Recv, Varbinds]), + "~n self(): ~p" + "~n Agent: ~p [~p]" + "~n Trap: ~p" + "~n NotifyName: ~p" + "~n CtxName: ~p" + "~n Recv: ~p" + "~n Varbinds: ~p", + [self(), Agent, wis(Agent), + Trap, NotifyName, CtxName, Recv, Varbinds]), Msg = {send_trap, Trap, NotifyName, CtxName, Recv, Varbinds}, case (wis(Agent) =:= self()) of false -> @@ -540,6 +546,27 @@ send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds) -> Agent ! Msg end. +send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID) -> + ?d("send_trap -> entry with" + "~n self(): ~p" + "~n Agent: ~p [~p]" + "~n Trap: ~p" + "~n NotifyName: ~p" + "~n CtxName: ~p" + "~n Recv: ~p" + "~n Varbinds: ~p" + "~n LocalEngineID: ~p", + [self(), Agent, wis(Agent), + Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID]), + Msg = + {send_trap, Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID}, + case (wis(Agent) =:= self()) of + false -> + call(Agent, Msg); + true -> + Agent ! Msg + end. + %% -- Discovery functions -- @@ -626,6 +653,7 @@ wis(Pid) when is_pid(Pid) -> wis(Atom) when is_atom(Atom) -> whereis(Atom). + forward_trap(Agent, TrapRecord, NotifyName, CtxName, Recv, Varbinds) -> Agent ! {forward_trap, TrapRecord, NotifyName, CtxName, Recv, Varbinds}. @@ -719,14 +747,15 @@ handle_info(worker_available, S) -> handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, S) -> ?vlog("[handle_info] send trap request:" - "~n Trap: ~p" - "~n NotifyName: ~p" - "~n ContextName: ~p" - "~n Recv: ~p" - "~n Varbinds: ~p", - [Trap,NotifyName,ContextName,Recv,Varbinds]), + "~n Trap: ~p" + "~n NotifyName: ~p" + "~n ContextName: ~p" + "~n Recv: ~p" + "~n Varbinds: ~p", + [Trap, NotifyName, ContextName, Recv, Varbinds]), + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, case catch handle_send_trap(S, Trap, NotifyName, ContextName, - Recv, Varbinds) of + Recv, Varbinds, LocalEngineID) of {ok, NewS} -> {noreply, NewS}; {'EXIT', R} -> @@ -736,17 +765,39 @@ handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, S) -> {noreply, S} end; -handle_info({forward_trap, TrapRecord, NotifyName, ContextName, - Recv, Varbinds},S) -> +handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds, + LocalEngineID}, S) -> + ?vlog("[handle_info] send trap request:" + "~n Trap: ~p" + "~n NotifyName: ~p" + "~n ContextName: ~p" + "~n Recv: ~p" + "~n Varbinds: ~p" + "~n LocalEngineID: ~p", + [Trap, NotifyName, ContextName, Recv, Varbinds, LocalEngineID]), + case catch handle_send_trap(S, Trap, NotifyName, ContextName, + Recv, Varbinds, LocalEngineID) of + {ok, NewS} -> + {noreply, NewS}; + {'EXIT', R} -> + ?vinfo("Trap not sent:~n ~p", [R]), + {noreply, S}; + _ -> + {noreply, S} + end; + +handle_info({forward_trap, TrapRecord, NotifyName, ContextName, + Recv, Varbinds}, S) -> ?vlog("[handle_info] forward trap request:" - "~n TrapRecord: ~p" - "~n NotifyName: ~p" - "~n ContextName: ~p" - "~n Recv: ~p" - "~n Varbinds: ~p", - [TrapRecord,NotifyName,ContextName,Recv,Varbinds]), + "~n TrapRecord: ~p" + "~n NotifyName: ~p" + "~n ContextName: ~p" + "~n Recv: ~p" + "~n Varbinds: ~p", + [TrapRecord, NotifyName, ContextName, Recv, Varbinds]), + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, case (catch maybe_send_trap(S, TrapRecord, NotifyName, ContextName, - Recv, Varbinds)) of + Recv, Varbinds, LocalEngineID)) of {ok, NewS} -> {noreply, NewS}; {'EXIT', R} -> @@ -856,17 +907,52 @@ handle_call(restart_set_worker, _From, #state{set_worker = Pid} = S) -> ok end, {reply, ok, S}; + handle_call({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, _From, S) -> ?vlog("[handle_call] send trap request:" - "~n Trap: ~p" - "~n NotifyName: ~p" - "~n ContextName: ~p" - "~n Recv: ~p" - "~n Varbinds: ~p", - [Trap,NotifyName,ContextName,Recv,Varbinds]), + "~n Trap: ~p" + "~n NotifyName: ~p" + "~n ContextName: ~p" + "~n Recv: ~p" + "~n Varbinds: ~p", + [Trap, NotifyName, ContextName, Recv, Varbinds]), + LocalEngineID = + case S#state.type of + master_agent -> + ?DEFAULT_LOCAL_ENGINE_ID; + _ -> + %% subagent - + %% we don't need this, eventually the trap sent request + %% will reach the master-agent and then it will look up + %% the proper engine id. + ignore + end, + case (catch handle_send_trap(S, Trap, NotifyName, ContextName, + Recv, Varbinds, LocalEngineID)) of + {ok, NewS} -> + {reply, ok, NewS}; + {'EXIT', Reason} -> + ?vinfo("Trap not sent:~n ~p", [Reason]), + {reply, {error, {send_failed, Reason}}, S}; + _ -> + ?vinfo("Trap not sent", []), + {reply, {error, send_failed}, S} + end; + +handle_call({send_trap, Trap, NotifyName, + ContextName, Recv, Varbinds, LocalEngineID}, + _From, S) -> + ?vlog("[handle_call] send trap request:" + "~n Trap: ~p" + "~n NotifyName: ~p" + "~n ContextName: ~p" + "~n Recv: ~p" + "~n Varbinds: ~p" + "~n LocalEngineID: ~p", + [Trap, NotifyName, ContextName, Recv, Varbinds, LocalEngineID]), case (catch handle_send_trap(S, Trap, NotifyName, ContextName, - Recv, Varbinds)) of + Recv, Varbinds, LocalEngineID)) of {ok, NewS} -> {reply, ok, NewS}; {'EXIT', Reason} -> @@ -876,8 +962,10 @@ handle_call({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, ?vinfo("Trap not sent", []), {reply, {error, send_failed}, S} end; + handle_call({discovery, - TargetName, Notification, ContextName, Vbs, DiscoHandler, ExtraInfo}, + TargetName, Notification, ContextName, Vbs, DiscoHandler, + ExtraInfo}, From, #state{disco = undefined} = S) -> ?vlog("[handle_call] initiate discovery process:" @@ -1219,6 +1307,8 @@ handle_mibs_cache_request(MibServer, Req) -> snmpa_mib:gc_cache(MibServer, Age); {gc_cache, Age, GcLimit} -> snmpa_mib:gc_cache(MibServer, Age, GcLimit); + cache_size -> + snmpa_mib:which_cache_size(MibServer); enable_cache -> snmpa_mib:enable_cache(MibServer); disable_cache -> @@ -1432,17 +1522,20 @@ spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, Extra) -> Args = [Vsn, Pdu, PduMS, ACMData, Address, Extra, Dict], proc_lib:spawn_link(?MODULE, handle_pdu, Args). -spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, V) -> +spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID) -> Dict = get(), proc_lib:spawn_link(?MODULE, do_send_trap, - [TrapRec, NotifyName, ContextName, Recv, V, Dict]). + [TrapRec, NotifyName, ContextName, + Recv, Vbs, LocalEngineID, Dict]). -do_send_trap(TrapRec, NotifyName, ContextName, Recv, V, Dict) -> +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))), ?vlog("starting",[]), - snmpa_trap:send_trap(TrapRec, NotifyName, ContextName, Recv, V, - get(net_if)). + snmpa_trap:send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID, get(net_if)). worker(Master, Dict) -> lists:foreach(fun({Key, Val}) -> put(Key, Val) end, Dict), @@ -1457,17 +1550,22 @@ worker_loop(Master) -> handle_pdu(Vsn, Pdu, PduMS, ACMData, Address, Extra), Master ! worker_available; - %% Old style message - {MibView, Vsn, Pdu, PduMS, ACMData, AgentData, Extra} -> - ?vtrace("worker_loop -> received (old) request", []), - do_handle_pdu(MibView, Vsn, Pdu, PduMS, ACMData, AgentData, Extra), + %% 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; - {TrapRec, NotifyName, ContextName, Recv, V} -> % We don't trap exits! + %% 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, V, get(net_if)), + ContextName, Recv, Vbs, LocalEngineID, + get(net_if)), Master ! worker_available; {verbosity, Verbosity} -> @@ -1616,13 +1714,15 @@ handle_acm_error(Vsn, Reason, Pdu, ACMData, Address, Extra) -> end. -handle_send_trap(S, TrapName, NotifyName, ContextName, Recv, Varbinds) -> +handle_send_trap(S, TrapName, NotifyName, ContextName, Recv, Varbinds, + LocalEngineID) -> ?vtrace("handle_send_trap -> entry with" - "~n S#state.type: ~p" - "~n TrapName: ~p" - "~n NotifyName: ~p" - "~n ContextName: ~p", - [S#state.type, TrapName, NotifyName, ContextName]), + "~n S#state.type: ~p" + "~n TrapName: ~p" + "~n NotifyName: ~p" + "~n ContextName: ~p" + "~n LocalEngineID: ~p", + [S#state.type, TrapName, NotifyName, ContextName, LocalEngineID]), case snmpa_trap:construct_trap(TrapName, Varbinds) of {ok, TrapRecord, VarList} -> ?vtrace("handle_send_trap -> construction complete: " @@ -1639,7 +1739,8 @@ handle_send_trap(S, TrapName, NotifyName, ContextName, Recv, Varbinds) -> ?vtrace("handle_send_trap -> " "[master] handle send trap",[]), maybe_send_trap(S, TrapRecord, NotifyName, - ContextName, Recv, VarList) + ContextName, Recv, VarList, + LocalEngineID) end; error -> error @@ -1676,7 +1777,8 @@ maybe_forward_trap(#state{parent = Parent, nfilters = NFs} = S, maybe_send_trap(#state{nfilters = NFs} = S, - TrapRec, NotifyName, ContextName, Recv, Varbinds) -> + TrapRec, NotifyName, ContextName, Recv, Varbinds, + LocalEngineID) -> ?vtrace("maybe_send_trap -> entry with" "~n NFs: ~p", [NFs]), case filter_notification(NFs, [], TrapRec) of @@ -1693,39 +1795,45 @@ maybe_send_trap(#state{nfilters = NFs} = S, ?vtrace("maybe_send_trap -> send trap:" "~n ~p", [TrapRec2]), do_handle_send_trap(S, TrapRec2, - NotifyName, ContextName, Recv, Varbinds); + NotifyName, ContextName, Recv, Varbinds, + LocalEngineID); {send, Removed, TrapRec2} -> ?vtrace("maybe_send_trap -> send trap:" "~n ~p", [TrapRec2]), NFs2 = del_notification_filter(Removed, NFs), do_handle_send_trap(S#state{nfilters = NFs2}, TrapRec2, - NotifyName, ContextName, Recv, Varbinds) + NotifyName, ContextName, Recv, Varbinds, + LocalEngineID) end. -do_handle_send_trap(S, TrapRec, NotifyName, ContextName, Recv, Varbinds) -> - V = snmpa_trap:try_initialise_vars(get(mibserver), Varbinds), +do_handle_send_trap(S, TrapRec, NotifyName, ContextName, Recv, Varbinds, + LocalEngineID) -> + Vbs = snmpa_trap:try_initialise_vars(get(mibserver), Varbinds), case S#state.type of subagent -> forward_trap(S#state.parent, TrapRec, NotifyName, ContextName, - Recv, V), + Recv, Vbs), {ok, S}; master_agent when S#state.multi_threaded =:= false -> ?vtrace("do_handle_send_trap -> send trap:" "~n ~p", [TrapRec]), snmpa_trap:send_trap(TrapRec, NotifyName, ContextName, - Recv, V, get(net_if)), + Recv, Vbs, LocalEngineID, get(net_if)), {ok, S}; master_agent when S#state.worker_state =:= busy -> %% Main worker busy => create new worker ?vtrace("do_handle_send_trap -> main worker busy: " "spawn a trap sender", []), - spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, V), + spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID), {ok, S}; master_agent -> %% Send to main worker ?vtrace("do_handle_send_trap -> send to main worker",[]), - S#state.worker ! {TrapRec, NotifyName, ContextName, Recv, V}, + S#state.worker ! {send_trap, + TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID}, {ok, S#state{worker_state = busy}} end. diff --git a/lib/snmp/src/agent/snmpa_internal.hrl b/lib/snmp/src/agent/snmpa_internal.hrl index a33a6809dc..9fa874f119 100644 --- a/lib/snmp/src/agent/snmpa_internal.hrl +++ b/lib/snmp/src/agent/snmpa_internal.hrl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2006-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -22,6 +22,8 @@ -include_lib("snmp/src/app/snmp_internal.hrl"). +-define(DEFAULT_LOCAL_ENGINE_ID, snmp_framework_mib:get_engine_id()). + -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_mib.erl b/lib/snmp/src/agent/snmpa_mib.erl index 370989d0be..ce90db18b3 100644 --- a/lib/snmp/src/agent/snmpa_mib.erl +++ b/lib/snmp/src/agent/snmpa_mib.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(snmpa_mib). @@ -55,7 +55,7 @@ -define(NO_CACHE, no_mibs_cache). -define(DEFAULT_CACHE_USAGE, true). -define(CACHE_GC_TICKTIME, timer:minutes(1)). --define(DEFAULT_CACHE_AUTOGC, false). +-define(DEFAULT_CACHE_AUTOGC, true). -define(DEFAULT_CACHE_GCLIMIT, 100). -define(DEFAULT_CACHE_AGE, timer:minutes(10)). -define(CACHE_GC_TRIGGER, cache_gc_trigger). diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl index 2e09286b87..fd75b98f84 100644 --- a/lib/snmp/src/agent/snmpa_mpd.erl +++ b/lib/snmp/src/agent/snmpa_mpd.erl @@ -1,27 +1,28 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(snmpa_mpd). -export([init/1, reset/0, inc/1, counters/0, discarded_pdu/1, - process_packet/6, - generate_response_msg/5, generate_msg/5, + process_packet/6, process_packet/7, + generate_response_msg/5, generate_response_msg/6, + generate_msg/5, generate_msg/6, generate_discovery_msg/4, process_taddrs/1, generate_req_id/0]). @@ -34,6 +35,7 @@ -define(VMODULE,"MPD"). -include("snmp_verbosity.hrl"). +-include("snmpa_internal.hrl"). -define(empty_msg_size, 24). @@ -120,6 +122,12 @@ reset() -> %% section 4.2.1 in rfc2272) %%----------------------------------------------------------------- process_packet(Packet, TDomain, TAddress, State, NoteStore, Log) -> + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + process_packet(Packet, TDomain, TAddress, LocalEngineID, + State, NoteStore, Log). + +process_packet(Packet, TDomain, TAddress, LocalEngineID, + State, NoteStore, Log) -> inc(snmpInPkts), case catch snmp_pdus:dec_message_only(binary_to_list(Packet)) of @@ -127,15 +135,17 @@ process_packet(Packet, TDomain, TAddress, State, NoteStore, Log) -> when State#state.v1 =:= true -> ?vlog("v1, community: ~s", [Community]), HS = ?empty_msg_size + length(Community), - v1_v2c_proc('version-1', NoteStore, Community, TDomain, TAddress, - Data, HS, Log, Packet); + v1_v2c_proc('version-1', NoteStore, Community, + TDomain, TAddress, + LocalEngineID, Data, HS, Log, Packet); #message{version = 'version-2', vsn_hdr = Community, data = Data} when State#state.v2c =:= true -> ?vlog("v2c, community: ~s", [Community]), HS = ?empty_msg_size + length(Community), - v1_v2c_proc('version-2', NoteStore, Community, TDomain, TAddress, - Data, HS, Log, Packet); + v1_v2c_proc('version-2', NoteStore, Community, + TDomain, TAddress, + LocalEngineID, Data, HS, Log, Packet); #message{version = 'version-3', vsn_hdr = V3Hdr, data = Data} when State#state.v3 =:= true -> @@ -143,7 +153,9 @@ process_packet(Packet, TDomain, TAddress, State, NoteStore, Log) -> [V3Hdr#v3_hdr.msgID, V3Hdr#v3_hdr.msgFlags, V3Hdr#v3_hdr.msgSecurityModel]), - v3_proc(NoteStore, Packet, TDomain, TAddress, V3Hdr, Data, Log); + v3_proc(NoteStore, Packet, + TDomain, TAddress, + LocalEngineID, V3Hdr, Data, Log); {'EXIT', {bad_version, Vsn}} -> ?vtrace("exit: bad version: ~p",[Vsn]), @@ -170,10 +182,11 @@ discarded_pdu(Variable) -> inc(Variable). %%----------------------------------------------------------------- %% Handles a Community based message (v1 or v2c). %%----------------------------------------------------------------- -v1_v2c_proc(Vsn, NoteStore, Community, snmpUDPDomain, {Ip, Udp}, +v1_v2c_proc(Vsn, NoteStore, Community, snmpUDPDomain, + {Ip, Udp}, LocalEngineID, Data, HS, Log, Packet) -> TAddress = tuple_to_list(Ip) ++ [Udp div 256, Udp rem 256], - AgentMS = snmp_framework_mib:get_engine_max_message_size(), + AgentMS = get_engine_max_message_size(LocalEngineID), MgrMS = snmp_community_mib:get_target_addr_ext_mms(?snmpUDPDomain, TAddress), PduMS = case MgrMS of @@ -220,10 +233,10 @@ v1_v2c_proc(Vsn, NoteStore, Community, snmpUDPDomain, {Ip, Udp}, {discarded, trap_pdu} end; v1_v2c_proc(_Vsn, _NoteStore, _Community, snmpUDPDomain, TAddress, - _Data, _HS, _Log, _Packet) -> + _LocalEngineID, _Data, _HS, _Log, _Packet) -> {discarded, {badarg, TAddress}}; v1_v2c_proc(_Vsn, _NoteStore, _Community, TDomain, _TAddress, - _Data, _HS, _Log, _Packet) -> + _LocalEngineID, _Data, _HS, _Log, _Packet) -> {discarded, {badarg, TDomain}}. sec_model('version-1') -> ?SEC_V1; @@ -234,15 +247,19 @@ sec_model('version-2') -> ?SEC_V2C. %% Handles a SNMPv3 Message, following the procedures in rfc2272, %% section 4.2 and 7.2 %%----------------------------------------------------------------- -v3_proc(NoteStore, Packet, _TDomain, _TAddress, V3Hdr, Data, Log) -> - case (catch v3_proc(NoteStore, Packet, V3Hdr, Data, Log)) of +v3_proc(NoteStore, Packet, _TDomain, _TAddress, LocalEngineID, + V3Hdr, Data, Log) -> + case (catch v3_proc(NoteStore, Packet, LocalEngineID, V3Hdr, Data, Log)) of {'EXIT', Reason} -> exit(Reason); Result -> Result end. -v3_proc(NoteStore, Packet, V3Hdr, Data, Log) -> +v3_proc(NoteStore, Packet, LocalEngineID, V3Hdr, Data, Log) -> + ?vtrace("v3_proc -> entry with" + "~n LocalEngineID: ~p", + [LocalEngineID]), %% 7.2.3 #v3_hdr{msgID = MsgID, msgMaxSize = MMS, @@ -250,7 +267,7 @@ v3_proc(NoteStore, Packet, V3Hdr, Data, Log) -> msgSecurityModel = MsgSecurityModel, msgSecurityParameters = SecParams, hdr_size = HdrSize} = V3Hdr, - ?vdebug("v3_proc -> version 3 message header:" + ?vdebug("v3_proc -> version 3 message header [7.2.3]:" "~n msgID = ~p" "~n msgMaxSize = ~p" "~n msgFlags = ~p" @@ -263,17 +280,19 @@ v3_proc(NoteStore, Packet, V3Hdr, Data, Log) -> SecLevel = check_sec_level(MsgFlags), IsReportable = snmp_misc:is_reportable(MsgFlags), %% 7.2.6 - ?vtrace("v3_proc -> " + ?vtrace("v3_proc -> [7.2.6]" "~n SecModule = ~p" "~n SecLevel = ~p" "~n IsReportable = ~p", - [SecModule,SecLevel,IsReportable]), + [SecModule, SecLevel, IsReportable]), SecRes = (catch SecModule:process_incoming_msg(Packet, Data, - SecParams, SecLevel)), + SecParams, SecLevel, + LocalEngineID)), ?vtrace("v3_proc -> message processing result: " "~n SecRes: ~p", [SecRes]), {SecEngineID, SecName, ScopedPDUBytes, SecData, DiscoOrPlain} = - check_sec_module_result(SecRes, V3Hdr, Data, IsReportable, Log), + check_sec_module_result(SecRes, V3Hdr, Data, + LocalEngineID, IsReportable, Log), ?vtrace("v3_proc -> " "~n DiscoOrPlain: ~w" "~n SecEngineID: ~w" @@ -311,7 +330,7 @@ v3_proc(NoteStore, Packet, V3Hdr, Data, Log) -> Log(PDU#pdu.type, Packet) end, %% Make sure a get_bulk doesn't get too big. - AgentMS = snmp_framework_mib:get_engine_max_message_size(), + AgentMS = get_engine_max_message_size(LocalEngineID), %% PduMMS is supposed to be the maximum total length of the response %% PDU we can send. From the MMS, we need to subtract everything before %% the PDU, i.e. Message and ScopedPDU. @@ -415,8 +434,8 @@ v3_proc(NoteStore, Packet, V3Hdr, Data, Log) -> throw({discarded, received_v2_trap}); Type -> %% 7.2.13 - SnmpEngineID = snmp_framework_mib:get_engine_id(), - ?vtrace("v3_proc -> SnmpEngineID = ~w", [SnmpEngineID]), + SnmpEngineID = LocalEngineID, + ?vtrace("v3_proc -> 7.2.13", []), case SecEngineID of SnmpEngineID when (DiscoOrPlain =:= discovery) -> %% This is a discovery step 2 message! @@ -429,6 +448,7 @@ v3_proc(NoteStore, Packet, V3Hdr, Data, Log) -> ContextName, SecData, PDU, + LocalEngineID, Log); SnmpEngineID when (DiscoOrPlain =:= plain) -> @@ -444,17 +464,18 @@ v3_proc(NoteStore, Packet, V3Hdr, Data, Log) -> %% 4.2.2.1.2 NIsReportable = snmp_misc:is_reportable_pdu(Type), Val = inc(snmpUnknownPDUHandlers), - ErrorInfo = {#varbind{oid = ?snmpUnknownPDUHandlers, - variabletype = 'Counter32', - value = Val}, - SecName, - [{securityLevel, SecLevel}, - {contextEngineID, ContextEngineID}, - {contextName, ContextName}]}, + ErrorInfo = + {#varbind{oid = ?snmpUnknownPDUHandlers, + variabletype = 'Counter32', + value = Val}, + SecName, + [{securityLevel, SecLevel}, + {contextEngineID, ContextEngineID}, + {contextName, ContextName}]}, case generate_v3_report_msg(MsgID, MsgSecurityModel, - Data, ErrorInfo, - Log) of + Data, LocalEngineID, + ErrorInfo, Log) of {ok, Report} when NIsReportable =:= true -> {discarded, snmpUnknownPDUHandlers, Report}; _ -> @@ -473,6 +494,7 @@ v3_proc(NoteStore, Packet, V3Hdr, Data, Log) -> ContextName, SecData, PDU, + LocalEngineID, Log); _ -> @@ -501,7 +523,7 @@ check_sec_level(Unknown) -> inc(snmpInvalidMsgs), throw({discarded, snmpInvalidMsgs}). -check_sec_module_result(Res, V3Hdr, Data, IsReportable, Log) -> +check_sec_module_result(Res, V3Hdr, Data, LocalEngineID, IsReportable, Log) -> case Res of {ok, X} -> X; @@ -516,7 +538,7 @@ check_sec_module_result(Res, V3Hdr, Data, IsReportable, Log) -> #v3_hdr{msgID = MsgID, msgSecurityModel = MsgSecModel} = V3Hdr, Pdu = get_scoped_pdu(Data), case generate_v3_report_msg(MsgID, MsgSecModel, Pdu, - ErrorInfo, Log) of + LocalEngineID, ErrorInfo, Log) of {ok, Report} -> throw({discarded, {securityError, Reason}, Report}); {discarded, _SomeOtherReason} -> @@ -545,8 +567,15 @@ get_scoped_pdu(D) -> generate_response_msg(Vsn, RePdu, Type, ACMData, Log) -> generate_response_msg(Vsn, RePdu, Type, ACMData, Log, 1). +generate_response_msg(Vsn, RePdu, Type, ACMData, Log, N) when is_integer(N) -> + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + generate_response_msg(Vsn, RePdu, Type, ACMData, LocalEngineID, Log, N); +generate_response_msg(Vsn, RePdu, Type, ACMData, LocalEngineID, Log) -> + generate_response_msg(Vsn, RePdu, Type, ACMData, LocalEngineID, Log, 1). + generate_response_msg(Vsn, RePdu, Type, {community, _SecModel, Community, _IpUdp}, + LocalEngineID, Log, _) -> case catch snmp_pdus:enc_pdu(RePdu) of {'EXIT', Reason} -> @@ -555,8 +584,9 @@ generate_response_msg(Vsn, RePdu, Type, [RePdu, Community, Reason]), {discarded, Reason}; PduBytes -> - Message = #message{version = Vsn, vsn_hdr = Community, - data = PduBytes}, + Message = #message{version = Vsn, + vsn_hdr = Community, + data = PduBytes}, case catch list_to_binary( snmp_pdus:enc_message_only(Message)) of {'EXIT', Reason} -> @@ -565,7 +595,7 @@ generate_response_msg(Vsn, RePdu, Type, [RePdu, Community, Reason]), {discarded, Reason}; Packet -> - MMS = snmp_framework_mib:get_engine_max_message_size(), + MMS = get_engine_max_message_size(LocalEngineID), case size(Packet) of Len when Len =< MMS -> Log(Type, Packet), @@ -584,6 +614,7 @@ generate_response_msg(Vsn, RePdu, Type, generate_response_msg(Vsn, RePdu, Type, {v3, MsgID, MsgSecurityModel, SecName, SecLevel, ContextEngineID, ContextName, SecData}, + LocalEngineID, Log, N) -> %% rfc2272: 7.1 steps 6-8 ScopedPDU = #scopedPdu{contextEngineID = ContextEngineID, @@ -596,7 +627,7 @@ generate_response_msg(Vsn, RePdu, Type, [RePdu, ContextName, Reason]), {discarded, Reason}; ScopedPDUBytes -> - AgentMS = snmp_framework_mib:get_engine_max_message_size(), + AgentMS = get_engine_max_message_size(LocalEngineID), V3Hdr = #v3_hdr{msgID = MsgID, msgMaxSize = AgentMS, msgFlags = snmp_misc:mk_msg_flags(Type, SecLevel), @@ -611,13 +642,14 @@ generate_response_msg(Vsn, RePdu, Type, ?SEC_USM -> snmpa_usm end, - SecEngineID = snmp_framework_mib:get_engine_id(), + SecEngineID = LocalEngineID, ?vtrace("generate_response_msg -> SecEngineID: ~w", [SecEngineID]), case (catch SecModule:generate_outgoing_msg(Message, SecEngineID, SecName, SecData, - SecLevel)) of + SecLevel, + LocalEngineID)) of {'EXIT', Reason} -> config_err("~p (message: ~p)", [Reason, Message]), {discarded, Reason}; @@ -668,12 +700,14 @@ generate_response_msg(Vsn, RePdu, Type, SecName, SecLevel, ContextEngineID, ContextName, - SecData}, Log, N+1) + SecData}, + LocalEngineID, Log, N+1) end end end. -generate_v3_report_msg(MsgID, MsgSecurityModel, Data, ErrorInfo, Log) -> +generate_v3_report_msg(MsgID, MsgSecurityModel, Data, LocalEngineID, + ErrorInfo, Log) -> {Varbind, SecName, Opts} = ErrorInfo, ReqId = if @@ -689,7 +723,7 @@ generate_v3_report_msg(MsgID, MsgSecurityModel, Data, ErrorInfo, Log) -> error_index = 0, varbinds = [Varbind]}, SecLevel = snmp_misc:get_option(securityLevel, Opts, 0), - SnmpEngineID = snmp_framework_mib:get_engine_id(), + SnmpEngineID = LocalEngineID, ContextEngineID = snmp_misc:get_option(contextEngineID, Opts, SnmpEngineID), ContextName = snmp_misc:get_option(contextName, Opts, ""), @@ -697,7 +731,8 @@ generate_v3_report_msg(MsgID, MsgSecurityModel, Data, ErrorInfo, Log) -> generate_response_msg('version-3', Pdu, report, {v3, MsgID, MsgSecurityModel, SecName, SecLevel, - ContextEngineID, ContextName, SecData}, Log). + ContextEngineID, ContextName, SecData}, + LocalEngineID, Log). %% req_id(#scopedPdu{data = #pdu{request_id = ReqId}}) -> %% ?vtrace("Report ReqId: ~p",[ReqId]), @@ -719,7 +754,8 @@ generate_discovery1_report_msg(MsgID, MsgSecurityModel, SecName, SecLevel, ContextEngineID, ContextName, {SecData, Oid, Value}, - #pdu{request_id = ReqId}, Log) -> + #pdu{request_id = ReqId}, + LocalEngineID, Log) -> ?vtrace("generate_discovery1_report_msg -> entry with" "~n ReqId: ~p" "~n Value: ~p", [ReqId, Value]), @@ -734,7 +770,8 @@ generate_discovery1_report_msg(MsgID, MsgSecurityModel, varbinds = [Varbind]}, case generate_response_msg('version-3', PduOut, report, {v3, MsgID, MsgSecurityModel, SecName, SecLevel, - ContextEngineID, ContextName, SecData}, Log) of + ContextEngineID, ContextName, SecData}, + LocalEngineID, Log) of {ok, Packet} -> {discovery, Packet}; Error -> @@ -745,7 +782,8 @@ generate_discovery1_report_msg(MsgID, MsgSecurityModel, generate_discovery2_report_msg(MsgID, MsgSecurityModel, SecName, SecLevel, ContextEngineID, ContextName, - SecData, #pdu{request_id = ReqId}, Log) -> + SecData, #pdu{request_id = ReqId}, + LocalEngineID, Log) -> ?vtrace("generate_discovery2_report_msg -> entry with" "~n ReqId: ~p", [ReqId]), SecModule = get_security_module(MsgSecurityModel), @@ -757,7 +795,8 @@ generate_discovery2_report_msg(MsgID, MsgSecurityModel, varbinds = [Vb]}, case generate_response_msg('version-3', PduOut, report, {v3, MsgID, MsgSecurityModel, SecName, SecLevel, - ContextEngineID, ContextName, SecData}, Log) of + ContextEngineID, ContextName, SecData}, + LocalEngineID, Log) of {ok, Packet} -> {discovery, Packet}; Error -> @@ -816,7 +855,11 @@ set_vb_null([]) -> %% Executed when a message that isn't a response is generated, i.e. %% a trap or an inform. %%----------------------------------------------------------------- -generate_msg(Vsn, _NoteStore, Pdu, {community, Community}, To) -> +generate_msg(Vsn, NoteStore, Pdu, ACMData, To) -> + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + generate_msg(Vsn, NoteStore, Pdu, ACMData, LocalEngineID, To). + +generate_msg(Vsn, _NoteStore, Pdu, {community, Community}, LocalEngineID, To) -> Message = #message{version = Vsn, vsn_hdr = Community, data = Pdu}, case catch list_to_binary(snmp_pdus:enc_message(Message)) of {'EXIT', Reason} -> @@ -825,7 +868,7 @@ generate_msg(Vsn, _NoteStore, Pdu, {community, Community}, To) -> [Pdu, Community, Reason]), {discarded, Reason}; Packet -> - AgentMax = snmp_framework_mib:get_engine_max_message_size(), + AgentMax = get_engine_max_message_size(LocalEngineID), case size(Packet) of Len when Len =< AgentMax -> {ok, mk_v1_v2_packet_list(To, Packet, Len, Pdu)}; @@ -838,9 +881,9 @@ generate_msg(Vsn, _NoteStore, Pdu, {community, Community}, To) -> end end; generate_msg('version-3', NoteStore, Pdu, - {v3, ContextEngineID, ContextName}, To) -> - %% rfc2272: 7.1.6 - ScopedPDU = #scopedPdu{contextEngineID = ContextEngineID, + {v3, ContextEngineID, ContextName}, LocalEngineID, To) -> + %% rfc2272: 7.1 step 6 + ScopedPDU = #scopedPdu{contextEngineID = LocalEngineID, contextName = ContextName, data = Pdu}, case (catch snmp_pdus:enc_scoped_pdu(ScopedPDU)) of @@ -851,7 +894,8 @@ generate_msg('version-3', NoteStore, Pdu, {discarded, Reason}; ScopedPDUBytes -> {ok, mk_v3_packet_list(NoteStore, To, ScopedPDUBytes, Pdu, - ContextEngineID, ContextName)} + ContextEngineID, ContextName, + LocalEngineID)} end. @@ -1094,17 +1138,21 @@ mk_msg_flags(PduType, SecLevel) -> mk_v3_packet_entry(NoteStore, Domain, Addr, {SecModel, SecName, SecLevel, TargetAddrName}, - ScopedPDUBytes, Pdu, ContextEngineID, ContextName) -> - %% 7.1.7 - ?vtrace("mk_v3_packet_entry -> entry - 7.1.7", []), - MsgID = generate_msg_id(), - PduType = Pdu#pdu.type, - MsgFlags = mk_msg_flags(PduType, SecLevel), + ScopedPDUBytes, Pdu, _ContextEngineID, ContextName, + LocalEngineID) -> + %% rfc2272 7.1 step 77 + ?vtrace("mk_v3_packet_entry -> entry - RFC2272-7.1:7", []), + MsgVersion = 'version-3', % 7.1:7a + MsgID = generate_msg_id(), % 7.1:7b + MaxMsgSz = get_max_message_size(), % 7.1:7c + PduType = Pdu#pdu.type, + MsgFlags = mk_msg_flags(PduType, SecLevel), % 7.1:7d + MsgSecModel = SecModel, % 7.1:7e V3Hdr = #v3_hdr{msgID = MsgID, - msgMaxSize = get_max_message_size(), + msgMaxSize = MaxMsgSz, msgFlags = MsgFlags, - msgSecurityModel = SecModel}, - Message = #message{version = 'version-3', + msgSecurityModel = MsgSecModel}, + Message = #message{version = MsgVersion, vsn_hdr = V3Hdr, data = ScopedPDUBytes}, SecModule = @@ -1113,12 +1161,21 @@ mk_v3_packet_entry(NoteStore, Domain, Addr, snmpa_usm end, + %% + %% 7.1:8 - If the PDU is from the Response Class or the Internal Class + %% securityEngineID = snmpEngineID (local/source) + %% 7.1:9 - If the PDU is from the Unconfirmed Class + %% securityEngineID = snmpEngineID (local/source) + %% else + %% securityEngineID = targetEngineID (remote/destination) + %% + %% 7.1.9a ?vtrace("mk_v3_packet_entry -> sec engine id - 7.1.9a", []), SecEngineID = case PduType of 'snmpv2-trap' -> - snmp_framework_mib:get_engine_id(); + LocalEngineID; _ -> %% This is the implementation dependent target engine id %% procedure. @@ -1141,8 +1198,9 @@ mk_v3_packet_entry(NoteStore, Domain, Addr, ?vdebug("mk_v3_packet_entry -> secEngineID: ~p", [SecEngineID]), %% 7.1.9b - case catch SecModule:generate_outgoing_msg(Message, SecEngineID, - SecName, [], SecLevel) of + case (catch SecModule:generate_outgoing_msg(Message, SecEngineID, + SecName, [], SecLevel, + LocalEngineID)) of {'EXIT', Reason} -> config_err("~p (message: ~p)", [Reason, Message]), skip; @@ -1169,7 +1227,7 @@ mk_v3_packet_entry(NoteStore, Domain, Addr, sec_model = SecModel, sec_name = SecName, sec_level = SecLevel, - ctx_engine_id = ContextEngineID, + ctx_engine_id = LocalEngineID, ctx_name = ContextName, disco = false, req_id = Pdu#pdu.request_id}, @@ -1180,15 +1238,16 @@ mk_v3_packet_entry(NoteStore, Domain, Addr, mk_v3_packet_list(NoteStore, To, - ScopedPDUBytes, Pdu, ContextEngineID, ContextName) -> + ScopedPDUBytes, Pdu, ContextEngineID, ContextName, + LocalEngineID) -> mk_v3_packet_list(NoteStore, To, ScopedPDUBytes, Pdu, - ContextEngineID, ContextName, []). + ContextEngineID, ContextName, LocalEngineID, []). mk_v3_packet_list(_, [], _ScopedPDUBytes, _Pdu, _ContextEngineID, _ContextName, - Acc) -> + _LocalEngineID, Acc) -> lists:reverse(Acc); %% This clause is for backward compatibillity reasons @@ -1196,20 +1255,21 @@ mk_v3_packet_list(_, [], mk_v3_packet_list(NoteStore, [{{?snmpUDPDomain, [A,B,C,D,U1,U2]}, SecData} | T], ScopedPDUBytes, Pdu, ContextEngineID, ContextName, - Acc) -> + LocalEngineID, Acc) -> case mk_v3_packet_entry(NoteStore, snmpUDPDomain, {{A,B,C,D}, U1 bsl 8 + U2}, SecData, ScopedPDUBytes, Pdu, - ContextEngineID, ContextName) of + ContextEngineID, ContextName, LocalEngineID) of skip -> mk_v3_packet_list(NoteStore, T, ScopedPDUBytes, Pdu, - ContextEngineID, ContextName, + ContextEngineID, ContextName, LocalEngineID, Acc); {ok, Entry} -> mk_v3_packet_list(NoteStore, T, ScopedPDUBytes, Pdu, - ContextEngineID, ContextName, [Entry | Acc]) + ContextEngineID, ContextName, LocalEngineID, + [Entry | Acc]) end; %% This is the new clause @@ -1218,11 +1278,11 @@ mk_v3_packet_list(NoteStore, mk_v3_packet_list(NoteStore, [{{Domain, Addr}, SecData} | T], ScopedPDUBytes, Pdu, ContextEngineID, ContextName, - Acc) -> + LocalEngineID, Acc) -> case mk_v3_packet_entry(NoteStore, Domain, Addr, SecData, ScopedPDUBytes, Pdu, - ContextEngineID, ContextName) of + ContextEngineID, ContextName, LocalEngineID) of skip -> mk_v3_packet_list(NoteStore, T, ScopedPDUBytes, Pdu, @@ -1230,7 +1290,8 @@ mk_v3_packet_list(NoteStore, {ok, Entry} -> mk_v3_packet_list(NoteStore, T, ScopedPDUBytes, Pdu, - ContextEngineID, ContextName, [Entry | Acc]) + ContextEngineID, ContextName, + LocalEngineID, [Entry | Acc]) end. @@ -1253,6 +1314,9 @@ gen(Id) -> get_target_engine_id(TargetAddrName) -> snmp_target_mib:get_target_engine_id(TargetAddrName). +get_engine_max_message_size(_LocalEngineID) -> + snmp_framework_mib:get_engine_max_message_size(). + sec_module(?SEC_USM) -> snmpa_usm. diff --git a/lib/snmp/src/agent/snmpa_trap.erl b/lib/snmp/src/agent/snmpa_trap.erl index b1096b1135..450cb2e9f4 100644 --- a/lib/snmp/src/agent/snmpa_trap.erl +++ b/lib/snmp/src/agent/snmpa_trap.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% -module(snmpa_trap). @@ -23,14 +23,18 @@ %%%----------------------------------------------------------------- %% External exports -export([construct_trap/2, - try_initialise_vars/2, send_trap/6]). + try_initialise_vars/2, + send_trap/6, send_trap/7]). -export([send_discovery/5]). %% Internal exports --export([init_v2_inform/9, init_v3_inform/9, send_inform/6]). +-export([init_v2_inform/9, + init_v3_inform/9, init_v3_inform/10, + send_inform/6]). -export([init_discovery_inform/12, send_discovery_inform/5]). -include("snmp_types.hrl"). +-include("snmpa_internal.hrl"). -include("SNMPv2-MIB.hrl"). -include("SNMPv2-TM.hrl"). -include("SNMPv2-TC.hrl"). @@ -331,13 +335,20 @@ make_varbind_list(Varbinds) -> %% SnmpTargetAddrTable (using the Tag). %%----------------------------------------------------------------- send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, NetIf) -> - (catch do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, NetIf)). + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID, NetIf). + +send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, NetIf) -> + (catch do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID, NetIf)). -do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, NetIf) -> +do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID, NetIf) -> VarbindList = make_varbind_list(Vbs), Dests = find_dests(NotifyName), send_trap_pdus(Dests, ContextName, {TrapRec, VarbindList}, [], [], [], - Recv, NetIf). + Recv, LocalEngineID, NetIf). send_discovery(TargetName, Record, ContextName, Vbs, NetIf) -> case find_dest(TargetName) of @@ -619,7 +630,9 @@ send_discovery_inform(Parent, Timeout, Retry, Msg, NetIf) -> %%----------------------------------------------------------------- send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel}, Type} | T], - ContextName,{TrapRec, Vbs}, V1Res, V2Res, V3Res, Recv, NetIf) -> + ContextName, + {TrapRec, Vbs}, V1Res, V2Res, V3Res, Recv, + LocalEngineID, NetIf) -> ?vdebug("send trap pdus: " "~n Destination address: ~p" "~n Target name: ~p" @@ -634,7 +647,7 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel}, case check_all_varbinds(TrapRec, Vbs, MibView) of true when MpModel =:= ?MP_V1 -> ?vtrace("send_trap_pdus -> v1 mp model",[]), - ContextEngineId = snmp_framework_mib:get_engine_id(), + ContextEngineId = LocalEngineID, case snmp_community_mib:vacm2community({SecName, ContextEngineId, ContextName}, @@ -644,16 +657,18 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel}, [element(2, DestAddr)]), send_trap_pdus(T, ContextName, {TrapRec, Vbs}, [{DestAddr, Community} | V1Res], - V2Res, V3Res, Recv, NetIf); + V2Res, V3Res, Recv, + LocalEngineID, NetIf); undefined -> ?vdebug("No community found for v1 dest: ~p", [element(2, DestAddr)]), send_trap_pdus(T, ContextName, {TrapRec, Vbs}, - V1Res, V2Res, V3Res, Recv, NetIf) + V1Res, V2Res, V3Res, Recv, + LocalEngineID, NetIf) end; true when MpModel =:= ?MP_V2C -> ?vtrace("send_trap_pdus -> v2c mp model",[]), - ContextEngineId = snmp_framework_mib:get_engine_id(), + ContextEngineId = LocalEngineID, case snmp_community_mib:vacm2community({SecName, ContextEngineId, ContextName}, @@ -664,12 +679,13 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel}, send_trap_pdus(T, ContextName, {TrapRec, Vbs}, V1Res, [{DestAddr, Community, Type}|V2Res], - V3Res, Recv, NetIf); + V3Res, Recv, LocalEngineID, NetIf); undefined -> ?vdebug("No community found for v2c dest: ~p", [element(2, DestAddr)]), send_trap_pdus(T, ContextName, {TrapRec, Vbs}, - V1Res, V2Res, V3Res, Recv, NetIf) + V1Res, V2Res, V3Res, Recv, + LocalEngineID, NetIf) end; true when MpModel =:= ?MP_V3 -> ?vtrace("send_trap_pdus -> v3 mp model",[]), @@ -678,18 +694,20 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel}, send_trap_pdus(T, ContextName, {TrapRec, Vbs}, V1Res, V2Res, [{DestAddr, MsgData, Type} | V3Res], - Recv, NetIf); + Recv, LocalEngineID, NetIf); true -> ?vlog("bad MpModel ~p for dest ~p", [MpModel, element(2, DestAddr)]), send_trap_pdus(T, ContextName, {TrapRec, Vbs}, - V1Res, V2Res, V3Res, Recv, NetIf); + V1Res, V2Res, V3Res, Recv, + LocalEngineID, NetIf); _ -> ?vlog("no access for dest: " "~n ~p in target ~p", [element(2, DestAddr), TargetName]), send_trap_pdus(T, ContextName, {TrapRec, Vbs}, - V1Res, V2Res, V3Res, Recv, NetIf) + V1Res, V2Res, V3Res, Recv, + LocalEngineID, NetIf) end; {discarded, Reason} -> ?vlog("mib view error ~p for" @@ -697,10 +715,10 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel}, "~n SecName: ~w", [Reason, element(2, DestAddr), SecName]), send_trap_pdus(T, ContextName, {TrapRec, Vbs}, - V1Res, V2Res, V3Res, Recv, NetIf) + V1Res, V2Res, V3Res, Recv, LocalEngineID, NetIf) end; send_trap_pdus([], ContextName, {TrapRec, Vbs}, V1Res, V2Res, V3Res, - Recv, NetIf) -> + Recv, LocalEngineID, NetIf) -> SysUpTime = snmp_standard_mib:sys_up_time(), ?vdebug("send trap pdus with sysUpTime ~p", [SysUpTime]), InformRecvs = get_inform_recvs(V2Res ++ V3Res), @@ -708,7 +726,8 @@ send_trap_pdus([], ContextName, {TrapRec, Vbs}, V1Res, V2Res, V3Res, deliver_recv(Recv, snmp_targets, InformTargets), send_v1_trap(TrapRec, V1Res, Vbs, NetIf, SysUpTime), send_v2_trap(TrapRec, V2Res, Vbs, Recv, NetIf, SysUpTime), - send_v3_trap(TrapRec, V3Res, Vbs, Recv, NetIf, SysUpTime, ContextName). + send_v3_trap(TrapRec, V3Res, Vbs, Recv, LocalEngineID, NetIf, + SysUpTime, ContextName). send_v1_trap(_TrapRec, [], _Vbs, _NetIf, _SysUpTime) -> ok; @@ -762,21 +781,25 @@ send_v2_trap(TrapRec, V2Res, Vbs, Recv, NetIf, SysUpTime) -> do_send_v2_trap(TrapRecvs, IVbs, NetIf), do_send_v2_inform(InformRecvs, IVbs, Recv, NetIf). -send_v3_trap(_TrapRec, [], _Vbs, _Recv, _NetIf, _SysUpTime, _ContextName) -> +send_v3_trap(_TrapRec, [], _Vbs, _Recv, _LocalEngineID, + _NetIf, _SysUpTime, _ContextName) -> ok; -send_v3_trap(TrapRec, V3Res, Vbs, Recv, NetIf, SysUpTime, ContextName) -> +send_v3_trap(TrapRec, V3Res, Vbs, Recv, LocalEngineID, + NetIf, SysUpTime, ContextName) -> ?vdebug("prepare to send v3 trap",[]), {_Oid, IVbs} = mk_v2_trap(TrapRec, Vbs, SysUpTime), % v2 refers to SMIv2; - TrapRecvs = get_trap_recvs(V3Res), % same SMI for v3 + TrapRecvs = get_trap_recvs(V3Res), % same SMI for v3 InformRecvs = get_inform_recvs(V3Res), do_send_v3_trap(TrapRecvs, ContextName, IVbs, NetIf), - do_send_v3_inform(InformRecvs, ContextName, IVbs, Recv, NetIf). + do_send_v3_inform(InformRecvs, ContextName, IVbs, Recv, + LocalEngineID, NetIf). mk_v2_trap(#notification{oid = Oid}, Vbs, SysUpTime) -> ?vtrace("make v2 notification '~p'",[Oid]), mk_v2_notif(Oid, Vbs, SysUpTime); -mk_v2_trap(#trap{enterpriseoid = Enter, specificcode = Spec}, Vbs, SysUpTime) -> +mk_v2_trap(#trap{enterpriseoid = Enter, specificcode = Spec}, + Vbs, SysUpTime) -> %% Use alg. in rfc1908 to map a v1 trap to a v2 trap ?vtrace("make v2 trap for '~p' with ~p",[Enter,Spec]), {Oid,Enterp} = @@ -845,16 +868,16 @@ do_send_v3_trap(Recvs, ContextName, Vbs, NetIf) -> end, Recvs), ok. -do_send_v3_inform([], _ContextName, _Vbs, _Recv, _NetIf) -> +do_send_v3_inform([], _ContextName, _Vbs, _Recv, _LocalEngineID, _NetIf) -> ok; -do_send_v3_inform(Recvs, ContextName, Vbs, Recv, NetIf) -> +do_send_v3_inform(Recvs, ContextName, Vbs, Recv, LocalEngineID, NetIf) -> lists:foreach( fun({Addr, MsgData, Timeout, Retry}) -> ?vtrace("~n start inform sender to send v3 inform to ~p", [Addr]), proc_lib:spawn_link(?MODULE, init_v3_inform, [{Addr, MsgData}, Timeout, Retry, Vbs, - Recv, NetIf, ContextName, + Recv, LocalEngineID, NetIf, ContextName, get(verbosity), get(sname)]) end, Recvs). @@ -874,7 +897,13 @@ init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, Community,V,S) -> %% New process -init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, ContextName,V,S) -> +init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, ContextName, V, S) -> + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID, + NetIf, ContextName, V, S). + +init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID, + NetIf, ContextName, V, S) -> %% Make a new Inform for each recipient; they need unique %% request-ids! put(verbosity,V), @@ -882,7 +911,7 @@ init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, ContextName,V,S) -> ?vdebug("~n starting with timeout = ~p and retry = ~p", [Timeout,Retry]), InformPdu = make_v2_notif_pdu(Vbs, 'inform-request'), % Yes, v2 - ContextEngineId = snmp_framework_mib:get_engine_id(), + ContextEngineId = LocalEngineID, Msg = {send_pdu_req, 'version-3', InformPdu, {v3, ContextEngineId, ContextName}, [Addr], self()}, ?MODULE:send_inform(Addr, Timeout*10, Retry, Msg, Recv, NetIf). diff --git a/lib/snmp/src/agent/snmpa_usm.erl b/lib/snmp/src/agent/snmpa_usm.erl index b94294844b..ae584bb3c1 100644 --- a/lib/snmp/src/agent/snmpa_usm.erl +++ b/lib/snmp/src/agent/snmpa_usm.erl @@ -19,8 +19,8 @@ -module(snmpa_usm). -export([ - process_incoming_msg/4, - generate_outgoing_msg/5, + process_incoming_msg/4, process_incoming_msg/5, + generate_outgoing_msg/5, generate_outgoing_msg/6, generate_discovery_msg/4, generate_discovery_msg/5, current_statsNotInTimeWindows_vb/0 ]). @@ -33,6 +33,7 @@ -define(VMODULE,"A-USM"). -include("snmp_verbosity.hrl"). +-include("snmpa_internal.hrl"). %%----------------------------------------------------------------- @@ -58,7 +59,11 @@ %%----------------------------------------------------------------- process_incoming_msg(Packet, Data, SecParams, SecLevel) -> - TermDiscoEnabled = is_terminating_discovery_enabled(), + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + process_incoming_msg(Packet, Data, SecParams, SecLevel, LocalEngineID). + +process_incoming_msg(Packet, Data, SecParams, SecLevel, LocalEngineID) -> + TermDiscoEnabled = is_terminating_discovery_enabled(), TermTriggerUsername = terminating_trigger_username(), %% 3.2.1 ?vtrace("process_incoming_msg -> check security parms: 3.2.1",[]), @@ -124,7 +129,7 @@ process_incoming_msg(Packet, Data, SecParams, SecLevel) -> "~n ~p",[UsmUser]), DiscoOrPlain = authenticate_incoming(Packet, UsmSecParams, UsmUser, - SecLevel), + SecLevel, LocalEngineID), %% 3.2.8 ?vtrace("process_incoming_msg -> " "decrypt scoped data: 3.2.8",[]), @@ -166,7 +171,8 @@ process_discovery_msg(MsgAuthEngineID, Data, SecLevel) -> end. -authenticate_incoming(Packet, UsmSecParams, UsmUser, SecLevel) -> +authenticate_incoming(Packet, UsmSecParams, UsmUser, SecLevel, + LocalEngineID) -> %% 3.2.6 ?vtrace("authenticate_incoming -> 3.2.6", []), AuthProtocol = element(?usmUserAuthProtocol, UsmUser), @@ -190,7 +196,8 @@ authenticate_incoming(Packet, UsmSecParams, UsmUser, SecLevel) -> SecName, MsgAuthEngineID, MsgAuthEngineBoots, - MsgAuthEngineTime) of + MsgAuthEngineTime, + LocalEngineID) of discovery -> discovery; true -> @@ -205,15 +212,15 @@ authenticate_incoming(Packet, UsmSecParams, UsmUser, SecLevel) -> plain end. -authoritative(SecName, MsgAuthEngineBoots, MsgAuthEngineTime) -> +authoritative(SecName, MsgAuthEngineBoots, MsgAuthEngineTime, LocalEngineID) -> ?vtrace("authoritative -> entry with" "~n SecName: ~p" "~n MsgAuthEngineBoots: ~p" "~n MsgAuthEngineTime: ~p", [SecName, MsgAuthEngineBoots, MsgAuthEngineTime]), - SnmpEngineBoots = snmp_framework_mib:get_engine_boots(), + SnmpEngineBoots = get_local_engine_boots(LocalEngineID), ?vtrace("authoritative -> SnmpEngineBoots: ~p", [SnmpEngineBoots]), - SnmpEngineTime = snmp_framework_mib:get_engine_time(), + SnmpEngineTime = get_local_engine_time(LocalEngineID), ?vtrace("authoritative -> SnmpEngineTime: ~p", [SnmpEngineTime]), InTimeWindow = if @@ -320,11 +327,12 @@ non_authoritative(SecName, end. -is_auth(?usmNoAuthProtocol, _, _, _, SecName, _, _, _) -> % 3.2.5 +is_auth(?usmNoAuthProtocol, _, _, _, SecName, _, _, _, _) -> % 3.2.5 error(usmStatsUnsupportedSecLevels, ?usmStatsUnsupportedSecLevels_instance, SecName); % OTP-5464 is_auth(AuthProtocol, AuthKey, AuthParams, Packet, SecName, - MsgAuthEngineID, MsgAuthEngineBoots, MsgAuthEngineTime) -> + MsgAuthEngineID, MsgAuthEngineBoots, MsgAuthEngineTime, + LocalEngineID) -> TermDiscoEnabled = is_terminating_discovery_enabled(), TermDiscoStage2 = terminating_discovery_stage2(), IsAuth = auth_in(AuthProtocol, AuthKey, AuthParams, Packet), @@ -334,7 +342,7 @@ is_auth(AuthProtocol, AuthKey, AuthParams, Packet, SecName, %% 3.2.7 ?vtrace("is_auth -> " "retrieve EngineBoots and EngineTime: 3.2.7",[]), - SnmpEngineID = snmp_framework_mib:get_engine_id(), + SnmpEngineID = LocalEngineID, ?vtrace("is_auth -> SnmpEngineID: ~p", [SnmpEngineID]), case MsgAuthEngineID of SnmpEngineID when ((MsgAuthEngineBoots =:= 0) andalso @@ -351,12 +359,14 @@ is_auth(AuthProtocol, AuthKey, AuthParams, Packet, SecName, %% This will *always* result in the manager *not* %% beeing in timewindow authoritative(SecName, - MsgAuthEngineBoots, MsgAuthEngineTime); + MsgAuthEngineBoots, MsgAuthEngineTime, + LocalEngineID); SnmpEngineID -> %% 3.2.7a ?vtrace("is_auth -> we are authoritative: 3.2.7a", []), authoritative(SecName, - MsgAuthEngineBoots, MsgAuthEngineTime); + MsgAuthEngineBoots, MsgAuthEngineTime, + LocalEngineID); _ -> %% 3.2.7b - we're non-authoritative ?vtrace("is_auth -> we are non-authoritative: 3.2.7b",[]), @@ -418,12 +428,19 @@ try_decrypt(?usmAesCfb128Protocol, generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel) -> + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel, + LocalEngineID). + +generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel, + LocalEngineID) -> %% 3.1.1 ?vtrace("generate_outgoing_msg -> [3.1.1] entry with" - "~n SecEngineID: ~p" - "~n SecName: ~p" - "~n SecLevel: ~w", - [SecEngineID, SecName, SecLevel]), + "~n SecEngineID: ~p" + "~n SecName: ~p" + "~n SecLevel: ~w" + "~n LocalEngineID: ~p", + [SecEngineID, SecName, SecLevel, LocalEngineID]), {UserName, AuthProtocol, PrivProtocol, AuthKey, PrivKey} = case SecData of [] -> % 3.1.1b @@ -439,7 +456,7 @@ generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel) -> element(?usmUserPrivKey, User)}; {_, Name,_,_,_,_,_,_,_,_,_,_,_, RowStatus,_,_} -> ?vdebug("generate_outgoing_msg -> " - "found user ~p with wrong row status: ~p", + "found not active user ~p: ~p", [Name, RowStatus]), error(unknownSecurityName); _ -> @@ -460,7 +477,7 @@ generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel) -> ScopedPduBytes = Message#message.data, {ScopedPduData, MsgPrivParams} = encrypt(ScopedPduBytes, PrivProtocol, PrivKey, SecLevel), - SnmpEngineID = snmp_framework_mib:get_engine_id(), + SnmpEngineID = LocalEngineID, ?vtrace("generate_outgoing_msg -> SnmpEngineID: ~p [3.1.6]", [SnmpEngineID]), %% 3.1.6 @@ -474,8 +491,8 @@ generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel) -> {get_engine_boots(SecEngineID), get_engine_time(SecEngineID)}; _ -> - {snmp_framework_mib:get_engine_boots(), - snmp_framework_mib:get_engine_time()} + {get_local_engine_boots(SnmpEngineID), + get_local_engine_time(SnmpEngineID)} end, %% 3.1.5 - 3.1.7 ?vtrace("generate_outgoing_msg -> [3.1.5 - 3.1.7]",[]), @@ -681,6 +698,19 @@ current_statsNotInTimeWindows_vb() -> value = get_counter(usmStatsNotInTimeWindows)}. + +%%----------------------------------------------------------------- +%% Future profing... +%%----------------------------------------------------------------- + +get_local_engine_boots(_LocalEngineID) -> + snmp_framework_mib:get_engine_boots(). + +get_local_engine_time(_LocalEngineID) -> + snmp_framework_mib:get_engine_time(). + + + %%----------------------------------------------------------------- %% We cache the local values of all non-auth engines we know. %% Keep the values in the snmp_agent_table. diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index aa3410fea3..9ad16ffad2 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -22,53 +22,91 @@ %% ----- U p g r a d e ------------------------------------------------------- [ + {"4.16.2", + [ + {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, []}, + + {load_module, snmpm_mpd, soft_purge, soft_purge, []} + ] + }, {"4.16.1", [ - {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_pdus, soft_purge, soft_purge, []}, {load_module, snmp_usm, soft_purge, soft_purge, []}, - {load_module, snmp_pdus, 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, [snmp_usm]}, + {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.16", [ - {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, - {load_module, snmp_usm, 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, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, {load_module, snmpa_general_db, soft_purge, soft_purge, []}, - {update, snmpm_net_if, soft, soft_purge, soft_purge, []} + {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_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + {update, snmpm_net_if, soft, soft_purge, soft_purge, []}, + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.15", [ - {load_module, snmp_pdus, soft_purge, soft_purge, []}, - {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, {load_module, snmp_config, 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, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp_log, snmpa_agent]}, {load_module, snmpa_general_db, soft_purge, soft_purge, []}, - {update, snmpm_net_if, {advanced, upgrade_from_pre_4_16}, - soft_purge, soft_purge, [snmpm_config, snmp_log]}, - {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16}, - soft_purge, soft_purge, [snmpa_agent, snmp_log]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, - {load_module, snmp_usm, soft_purge, soft_purge, []}, + {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16}, + soft_purge, soft_purge, [snmpa_agent, snmp_log]}, + {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, - {update, snmpm_config, soft, soft_purge, soft_purge, []} + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + {update, snmpm_net_if, {advanced, upgrade_from_pre_4_16}, + soft_purge, soft_purge, [snmpm_config, snmp_log]}, + {update, snmpm_config, soft, soft_purge, soft_purge, []}, + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.14", [ - {load_module, snmp_pdus, soft_purge, soft_purge, []}, - {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, {load_module, snmp_config, 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, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp_log, snmpa_agent]}, {load_module, snmpa_general_db, soft_purge, soft_purge, []}, - {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16}, - soft_purge, soft_purge, [snmpa_agent, snmp_log]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, - {load_module, snmp_usm, soft_purge, soft_purge, []}, + {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16}, + soft_purge, soft_purge, [snmp_log, snmpa_agent]}, + {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, {load_module, snmpm_user, soft_purge, soft_purge, []}, {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {update, snmpm_net_if, {advanced, upgrade_from_pre_4_16}, @@ -80,18 +118,22 @@ }, {"4.13.5", [ - {load_module, snmp_pdus, soft_purge, soft_purge, []}, - {load_module, snmpa_mib_data, soft_purge, soft_purge, []}, - {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, {load_module, snmp_config, 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, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp_log, snmpa_agent]}, {load_module, snmpa_general_db, soft_purge, soft_purge, []}, + {load_module, snmpa_mib_data, soft_purge, soft_purge, []}, + {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, + {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_net_if, {advanced, upgrade_from_pre_4_16}, soft_purge, soft_purge, [snmpa_agent, snmp_log]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, - {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, - {load_module, snmp_usm, soft_purge, soft_purge, []}, + {update, snmpa_mib, soft, soft_purge, soft_purge, [snmpa_mib_data]}, + {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, {load_module, snmpm_user, soft_purge, soft_purge, []}, {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {update, snmpm_net_if, {advanced, upgrade_from_pre_4_14}, @@ -107,54 +149,92 @@ %% ------D o w n g r a d e --------------------------------------------------- [ + {"4.16.2", + [ + {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, []}, + + {load_module, snmpm_mpd, soft_purge, soft_purge, []} + ] + }, {"4.16.1", [ - {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_pdus, soft_purge, soft_purge, []}, {load_module, snmp_usm, soft_purge, soft_purge, []}, - {load_module, snmp_pdus, 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, [snmp_usm]}, + {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.16", [ - {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, - {load_module, snmp_usm, 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, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent]}, {load_module, snmpa_general_db, soft_purge, soft_purge, []}, - {update, snmpm_net_if, soft, soft_purge, soft_purge, []} + {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_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + {update, snmpm_net_if, soft, soft_purge, soft_purge, []}, + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.15", [ - {load_module, snmp_pdus, soft_purge, soft_purge, []}, - {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, {load_module, snmp_config, soft_purge, soft_purge, []}, {load_module, snmp_log, soft_purge, soft_purge, []}, - {load_module, snmpa_general_db, soft_purge, soft_purge, []}, - {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16}, - soft_purge, soft_purge, [snmpa_agent, snmp_log]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, - {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, + {load_module, snmp_pdus, soft_purge, soft_purge, []}, {load_module, snmp_usm, soft_purge, soft_purge, []}, + {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent, snmp_log]}, {load_module, snmpa_general_db, soft_purge, soft_purge, []}, - {update, snmpm_net_if, {advanced, downgrade_to_pre_4_16}, + {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, + {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, + {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16}, + soft_purge, soft_purge, [snmpa_agent, snmp_log]}, + {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + {update, snmpm_net_if, {advanced, downgrade_to_pre_4_16}, soft_purge, soft_purge, [snmpm_config, snmp_log]}, - {update, snmpm_config, soft, soft_purge, soft_purge, []} + {update, snmpm_config, soft, soft_purge, soft_purge, []}, + {update, snmpm_server, soft, soft_purge, soft_purge, []} ] }, {"4.14", [ - {load_module, snmp_pdus, soft_purge, soft_purge, []}, - {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, {load_module, snmp_config, 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, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmpa_agent, snmp_log]}, {load_module, snmpa_general_db, soft_purge, soft_purge, []}, - {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16}, - soft_purge, soft_purge, [snmpa_agent, snmp_log]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, - {load_module, snmp_usm, soft_purge, soft_purge, []}, + {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16}, + soft_purge, soft_purge, [snmpa_agent, snmp_log]}, + {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, {load_module, snmpm_user, soft_purge, soft_purge, []}, {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {update, snmpm_net_if, {advanced, downgrade_to_pre_4_16}, @@ -166,18 +246,22 @@ }, {"4.13.5", [ - {load_module, snmp_pdus, soft_purge, soft_purge, []}, - {load_module, snmpa_mib_data, soft_purge, soft_purge, []}, {load_module, snmp_config, soft_purge, soft_purge, []}, - {load_module, snmpa, soft_purge, soft_purge, [snmp_log]}, {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_pdus, soft_purge, soft_purge, []}, + {load_module, snmp_usm, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp_log, snmpa_agent]}, {load_module, snmpa_general_db, soft_purge, soft_purge, []}, + {load_module, snmpa_mib_data, soft_purge, soft_purge, []}, + {load_module, snmpa_mpd, soft_purge, soft_purge, [snmpa_usm]}, + {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, {update, snmpa_net_if, {advanced, downgrade_to_pre_4_16}, soft_purge, soft_purge, [snmpa_agent, snmp_log]}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []}, - {load_module, snmpa_usm, soft_purge, soft_purge, [snmp_usm]}, - {load_module, snmp_usm, soft_purge, soft_purge, []}, + {update, snmpa_mib, soft, soft_purge, soft_purge, [snmpa_mib_data]}, + {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mib]}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, {load_module, snmpm_user, soft_purge, soft_purge, []}, {load_module, snmpm_user_default, soft_purge, soft_purge, [snmpm_user]}, {update, snmpm_net_if, {advanced, downgrade_to_pre_4_14}, diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl index d76ad20051..7712370d28 100644 --- a/lib/snmp/src/manager/snmpm_mpd.erl +++ b/lib/snmp/src/manager/snmpm_mpd.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -257,11 +257,11 @@ process_v3_msg(NoteStore, Msg, Hdr, Data, Addr, Port, Log) -> end, ?vlog("7.2.7" - "~n ContextEngineID: \"~s\" " + "~n ContextEngineID: ~p " "~n context: \"~s\" ", [CtxEngineID, CtxName]), if - SecLevel == 3 -> % encrypted message - log decrypted pdu + SecLevel =:= 3 -> % encrypted message - log decrypted pdu Log({Hdr, ScopedPDUBytes}); true -> % otherwise, log binary Log(Msg) @@ -338,7 +338,8 @@ process_v3_msg(NoteStore, Msg, Hdr, Data, Addr, Port, Log) -> SnmpEngineID = get_engine_id(), case SecEngineID of SnmpEngineID -> % 7.2.13.b - ?vtrace("valid securityEngineID: ~p", [SecEngineID]), + ?vtrace("7.2.13d - valid securityEngineID: ~p", + [SecEngineID]), %% 4.2.2.1.1 - we don't handle proxys yet => we only %% handle CtxEngineID to ourselves %% Check that we actually know of an agent with this @@ -353,7 +354,9 @@ process_v3_msg(NoteStore, Msg, Hdr, Data, Addr, Port, Log) -> {MsgID, MsgSecModel, SecName, SecLevel, CtxEngineID, CtxName, SecData}, {ok, 'version-3', PDU, PduMMS, ACMData}; - _ -> + UnknownEngineID -> + ?vtrace("4.2.2.1.2 - UnknownEngineId: ~p", + [UnknownEngineID]), %% 4.2.2.1.2 NIsReportable = snmp_misc:is_reportable_pdu(Type), Val = inc(snmpUnknownPDUHandlers), @@ -377,7 +380,8 @@ process_v3_msg(NoteStore, Msg, Hdr, Data, Addr, Port, Log) -> end end; _ -> % 7.2.13.a - ?vinfo("invalid securityEngineID: ~p",[SecEngineID]), + ?vinfo("7.2.13a - invalid securityEngineID: ~p", + [SecEngineID]), discard({badSecurityEngineID, SecEngineID}) end; diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl index 30aacc0ec3..d64b5b1d53 100644 --- a/lib/snmp/src/manager/snmpm_server.erl +++ b/lib/snmp/src/manager/snmpm_server.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -2804,16 +2804,16 @@ agent_data(TargetName, CtxName) -> agent_data(TargetName, CtxName, Config) -> case snmpm_config:agent_info(TargetName, all) of {ok, Info} -> - {value, {_, Version}} = lists:keysearch(version, 1, Info), + Version = agent_data_item(version, Info), MsgData = case Version of v3 -> DefSecModel = agent_data_item(sec_model, Info), DefSecName = agent_data_item(sec_name, Info), DefSecLevel = agent_data_item(sec_level, Info), - + EngineId = agent_data_item(engine_id, Info), - + SecModel = agent_data_item(sec_model, Config, DefSecModel), @@ -2829,7 +2829,7 @@ agent_data(TargetName, CtxName, Config) -> _ -> DefComm = agent_data_item(community, Info), DefSecModel = agent_data_item(sec_model, Info), - + Comm = agent_data_item(community, Config, DefComm), @@ -2848,8 +2848,12 @@ agent_data(TargetName, CtxName, Config) -> end. agent_data_item(Item, Info) -> - {value, {_, Val}} = lists:keysearch(Item, 1, Info), - Val. + case lists:keysearch(Item, 1, Info) of + {value, {_, Val}} -> + Val; + false -> + throw({error, {not_found, Item, Info}}) + end. agent_data_item(Item, Info, Default) -> case lists:keysearch(Item, 1, Info) of diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl index af0581150a..9d2e9969c4 100644 --- a/lib/snmp/test/snmp_agent_test.erl +++ b/lib/snmp/test/snmp_agent_test.erl @@ -1046,7 +1046,7 @@ v1_cases() -> sparse_table, cnt_64, opaque, - + change_target_addr_config ]. @@ -1977,7 +1977,8 @@ inform_i(Config) -> ?P1("unload TestTrap & TestTrapv2..."), ?line unload_master("TestTrap"), - ?line unload_master("TestTrapv2"). + ?line unload_master("TestTrapv2"), + ok. v3_inform_i(X) -> %% <CONDITIONAL-SKIP> @@ -3446,7 +3447,7 @@ do_mul_set_err() -> ?line ?v1_2(expect(2, noSuchName, 1, any), expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])), g([NewKeyc4]), - ?line ?v1_2(expect(3, noSuchName, 1, any), + ?line ?v1_2(expect(3, noSuchName, 1, any), expect(3, [{NewKeyc4, noSuchInstance}])). %% Req. SA-MIB @@ -3457,10 +3458,10 @@ sa_mib() -> ?line expect(2, [{[sa, [1,0]], "sa_test"}]). ma_trap1(MA) -> - snmpa:send_trap(MA, testTrap2, "standard trap"), + ok = snmpa:send_trap(MA, testTrap2, "standard trap"), ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]], "{mbj,eklas}@erlang.ericsson.se"}]), - snmpa:send_trap(MA, testTrap1, "standard trap"), + ok = snmpa:send_trap(MA, testTrap1, "standard trap"), ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]], "{mbj,eklas}@erlang.ericsson.se"}]). @@ -3509,7 +3510,8 @@ ma_v2_trap1(MA) -> ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]), snmpa:send_trap(MA, testTrapv21, "standard trap"), ?line expect(2, v2trap, [{[sysUpTime, 0], any}, - {[snmpTrapOID, 0], ?snmp ++ [1]}]). + {[snmpTrapOID, 0], ?snmp ++ [1]}]), + ok. ma_v2_trap2(MA) -> snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), @@ -3517,7 +3519,7 @@ ma_v2_trap2(MA) -> {[snmpTrapOID, 0], ?system ++ [0,1]}, {[system, [4,0]], "pelle"}]). -%% Note: This test case takes a while... actually a couple of minutes. +%% Note: This test case takes a while... actually a couple of minutes. ma_v2_inform1(MA) -> ?DBG("ma_v2_inform1 -> entry with" "~n MA = ~p => " @@ -5258,7 +5260,35 @@ otp_1131_2(X) -> ?P(otp_1131_2), otp_1131(X). otp_1131_3(X) -> %% <CONDITIONAL-SKIP> - Skippable = [{unix, [darwin]}], + %% This is intended to catch Montavista Linux 4.0/ppc (2.6.5) + %% Montavista Linux looks like a Debian distro (/etc/issue) + LinuxVersionVerify = + fun() -> + case os:cmd("uname -m") of + "ppc" ++ _ -> + case file:read_file_info("/etc/issue") of + {ok, _} -> + case os:cmd("grep -i montavista /etc/issue") of + Info when (is_list(Info) andalso + (length(Info) > 0)) -> + case os:version() of + {2, 6, 10} -> + true; + _ -> + false + end; + _ -> % Maybe plain Debian or Ubuntu + false + end; + _ -> + %% Not a Debian based distro + false + end; + _ -> + false + end + end, + Skippable = [{unix, [darwin, {linux, LinuxVersionVerify}]}], Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, ?NON_PC_TC_MAYBE_SKIP(X, Condition), %% </CONDITIONAL-SKIP> @@ -6219,12 +6249,15 @@ verify_old_info([Key|Keys], Info) -> is(S) -> [length(S) | S]. try_test(Func) -> + ?P2("try test ~w...", [Func]), snmp_agent_test_lib:try_test(?MODULE, Func). try_test(Func, A) -> + ?P2("try test ~w...", [Func]), snmp_agent_test_lib:try_test(?MODULE, Func, A). try_test(Func, A, Opts) -> + ?P2("try test ~w...", [Func]), snmp_agent_test_lib:try_test(?MODULE, Func, A, Opts). diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl index 31b375efa9..9e89aa889c 100644 --- a/lib/snmp/test/snmp_agent_test_lib.erl +++ b/lib/snmp/test/snmp_agent_test_lib.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -421,7 +421,7 @@ start_agent(Config, Vsns, Opts) -> ?LOG("start_agent -> entry (~p) with" "~n Config: ~p" "~n Vsns: ~p" - "~n Opts: ~p",[node(), Config, Vsns, Opts]), + "~n Opts: ~p", [node(), Config, Vsns, Opts]), ?line AgentDir = ?config(agent_dir, Config), ?line SaNode = ?config(snmp_sa, Config), diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl index 518b8b34de..cef96417dc 100644 --- a/lib/snmp/test/snmp_manager_test.erl +++ b/lib/snmp/test/snmp_manager_test.erl @@ -795,6 +795,35 @@ notify_started02(suite) -> []; notify_started02(Config) when is_list(Config) -> process_flag(trap_exit, true), put(tname,ns02), + + %% <CONDITIONAL-SKIP> + %% The point of this is to catch machines running + %% SLES9 (2.6.5) + LinuxVersionVerify = + fun() -> + case os:cmd("uname -m") of + "i686" ++ _ -> +%% io:format("found an i686 machine, " +%% "now check version~n", []), + case os:version() of + {2, 6, Rev} when Rev >= 16 -> + true; + {2, Min, _} when Min > 6 -> + true; + {Maj, _, _} when Maj > 2 -> + true; + _ -> + false + end; + _ -> + true + end + end, + Skippable = [{unix, [{linux, LinuxVersionVerify}]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + p("starting with Config: ~n~p", [Config]), ConfDir = ?config(manager_conf_dir, Config), diff --git a/lib/snmp/test/snmp_manager_user_test.erl b/lib/snmp/test/snmp_manager_user_test.erl index 24ed3b0b73..0f47d70873 100644 --- a/lib/snmp/test/snmp_manager_user_test.erl +++ b/lib/snmp/test/snmp_manager_user_test.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -822,10 +822,39 @@ register_monitor_and_crash3(doc) -> "Start a single user process, " "register-monitor one user and register one user, " "crash the single user process."; -register_monitor_and_crash3(Conf) when is_list(Conf) -> +register_monitor_and_crash3(Conf) when is_list(Conf) -> + process_flag(trap_exit, true), put(tname,rlac3), + + %% <CONDITIONAL-SKIP> + %% The point of this is to catch machines running + %% SLES9 (2.6.5) + LinuxVersionVerify = + fun() -> + case os:cmd("uname -m") of + "i686" ++ _ -> +%% io:format("found an i686 machine, " +%% "now check version~n", []), + case os:version() of + {2, 6, Rev} when Rev >= 16 -> + true; + {2, Min, _} when Min > 6 -> + true; + {Maj, _, _} when Maj > 2 -> + true; + _ -> + false + end; + _ -> + true + end + end, + Skippable = [{unix, [{linux, LinuxVersionVerify}]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Conf, Condition), + %% </CONDITIONAL-SKIP> + p("start"), - process_flag(trap_exit, true), ConfDir = ?config(manager_conf_dir, Conf), DbDir = ?config(manager_db_dir, Conf), diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl index 2586b66a13..54839d989b 100644 --- a/lib/snmp/test/snmp_test_lib.erl +++ b/lib/snmp/test/snmp_test_lib.erl @@ -1,19 +1,19 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 2002-2010. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% @@ -172,7 +172,17 @@ os_based_skip(Skippable) when is_list(Skippable) -> {value, {OsFam, OsName}} -> true; {value, {OsFam, OsNames}} when is_list(OsNames) -> - lists:member(OsName, OsNames); + case lists:member(OsName, OsNames) of + true -> + true; + false -> + case lists:keymember(OsName, 1, OsNames) of + {value, {OsName, Check}} when is_function(Check) -> + Check(); + _ -> + false + end + end; _ -> false end diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index 2fccc733e6..4ca1fb7901 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -17,162 +17,41 @@ # # %CopyrightEnd% -SNMP_VSN = 4.16.2 +SNMP_VSN = 4.17 PRE_VSN = APP_VSN = "snmp-$(SNMP_VSN)$(PRE_VSN)" -TICKETS = OTP-8563 OTP-8574 OTP-8594 OTP-8595 +TICKETS = OTP-8478 -TICKETS_4_16_1 = OTP-8480 OTP-8481 +TICKETS_4_16_2 = \ + OTP-8563 \ + OTP-8574 \ + OTP-8594 \ + OTP-8595 \ + OTP-8646 \ + OTP-8648 + +TICKETS_4_16_1 = \ + OTP-8480 \ + OTP-8481 TICKETS_4_16 = \ OTP-8395 \ OTP-8433 \ OTP-8442 -TICKETS_4_15 = OTP-8229 OTP-8249 - -TICKETS_4_14 = OTP-8223 OTP-8228 OTP-8237 - -TICKETS_4_13_5 = OTP-8116 OTP-8120 OTP-8181 OTP-8182 - -TICKETS_4_13_4 = OTP-8044 OTP-8062 OTP-8098 - -TICKETS_4_13_3 = OTP-8015 OTP-8020 - -TICKETS_4_13_2 = OTP-7961 OTP-7977 OTP-7983 OTP-7989 - -TICKETS_4_13_1 = OTP-7902 - -TICKETS_4_13 = OTP-7571 OTP-7735 OTP-7836 OTP-7851 - -TICKETS_4_12_2 = OTP-7868 - -TICKETS_4_12_1 = OTP-7695 OTP-7698 - -TICKETS_4_12 = OTP-7346 OTP-7525 - -TICKETS_4_11_2 = OTP-7570 OTP-7575 - -TICKETS_4_11_1 = OTP-7390 OTP-7412 OTP-7426 OTP-7432 - -TICKETS_4_11 = OTP-7201 OTP-7287 OTP-7319 OTP-7369 OTP-7371 OTP-7377 OTP-7381 - -TICKETS_4_10_3 = OTP-7219 - -TICKETS_4_10_2 = OTP-7152 OTP-7153 OTP-7157 OTP-7158 OTP-7159 OTP-7160 - -TICKETS_4_10_1 = OTP-7083 OTP-7109 OTP-7110 OTP-7119 OTP-7121 OTP-7123 - -TICKETS_4_10 = OTP-6649 OTP-6841 OTP-6898 OTP-6945 - -TICKETS_4_9_6 = OTP-6840 OTP-6843 - -TICKETS_4_9_5 = OTP-6805 OTP-6815 - -TICKETS_4_9_4 = OTP-6784 OTP-6771 - -TICKETS_4_9_3 = OTP-6605 OTP-6712 OTP-6713 - -TICKETS_4_9_2 = OTP-6571 - -TICKETS_4_9_1 = OTP-6566 OTP-6569 - -TICKETS_4_9 = \ - OTP-6317 \ - OTP-6318 \ - OTP-6383 \ - OTP-6487 \ - OTP-6515 \ - OTP-6518 \ - OTP-6529 \ - OTP-6532 \ - OTP-6533 \ - OTP-6540 - -TICKETS_4_8_4 = OTP-6408 - -TICKETS_4_8_3 = OTP-6337 OTP-6340 - -TICKETS_4_8_2 = OTP-6214 OTP-6247 OTP-6293 - -TICKETS_4_8_1 = OTP-6176 OTP-6177 - -TICKETS_4_8 = OTP-6137 OTP-6149 OTP-6150 OTP-6164 - -TICKETS_4_7_4 = \ - OTP-6042 \ - OTP-6044 \ - OTP-6049 \ - OTP-6062 \ - OTP-6068 \ - OTP-6074 \ - OTP-6077 \ - OTP-6081 - -TICKETS_4_7_3 = \ - OTP-6031 \ - OTP-6032 - -TICKETS_4_7_2 = \ - OTP-5992 \ - OTP-6024 - -TICKETS_4_7_1 = \ - OTP-5963 \ - OTP-5968 \ - OTP-5969 - -TICKETS_4_7 = \ - OTP-5870 \ - OTP-5934 \ - OTP-5935 \ - OTP-5937 - -TICKETS_4_6_1 = \ - OTP-5834 \ - OTP-5838 - -TICKETS_4_6 = \ - OTP-5763 \ - OTP-5771 \ - OTP-5787 \ - OTP-5797 \ - OTP-5829 - -TICKETS_4_5 = \ - OTP-5581 \ - OTP-5726 \ - OTP-5727 \ - OTP-5732 \ - OTP-5733 \ - OTP-5740 \ - OTP-5742 - -TICKETS_4_4_1 = \ - OTP-5719 \ - OTP-5720 - -TICKETS_4_4 = \ - OTP-5666 \ - OTP-5668 \ - OTP-5669 \ - OTP-5675 \ - OTP-5676 \ - OTP-5678 \ - OTP-5703 +TICKETS_4_15 = \ + OTP-8229 \ + OTP-8249 -TICKETS_4_3 = \ - OTP-5636 \ - OTP-5637 \ - OTP-5490 +TICKETS_4_14 = \ + OTP-8223 \ + OTP-8228 \ + OTP-8237 -TICKETS_4_2 = \ - OTP-5574 \ - OTP-5578 \ - OTP-5579 \ - OTP-5580 \ - OTP-5590 \ - OTP-5591 \ - OTP-5592 +TICKETS_4_13_5 = \ + OTP-8116 \ + OTP-8120 \ + OTP-8181 \ + OTP-8182 |