diff options
author | Micael Karlberg <[email protected]> | 2010-06-09 12:00:00 +0200 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2010-08-20 08:59:16 +0200 |
commit | 5af245e617ea5abad86131e194d304a66c72dd5d (patch) | |
tree | bd7f577e79cfc95fd2d6f01c0dd9c49a10cc37b5 /lib/snmp/src/agent | |
parent | 90e04f98a65a7f261ab9ba79917394b5d68bb650 (diff) | |
download | otp-5af245e617ea5abad86131e194d304a66c72dd5d.tar.gz otp-5af245e617ea5abad86131e194d304a66c72dd5d.tar.bz2 otp-5af245e617ea5abad86131e194d304a66c72dd5d.zip |
snmp: Patch 1125
OTP-8478 [agent] Added very basic support for multiple SNMPv3 EngineIDs
in a single agent.
Diffstat (limited to 'lib/snmp/src/agent')
-rw-r--r-- | lib/snmp/src/agent/snmpa.erl | 15 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_agent.erl | 223 | ||||
-rw-r--r-- | lib/snmp/src/agent/snmpa_internal.hrl | 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 |
6 files changed, 440 insertions, 205 deletions
diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl index 1c37d76074..87b191caed 100644 --- a/lib/snmp/src/agent/snmpa.erl +++ b/lib/snmp/src/agent/snmpa.erl @@ -61,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, @@ -423,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 648f5b53fa..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, @@ -65,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). @@ -529,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 -> @@ -545,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 -- @@ -631,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}. @@ -724,14 +747,36 @@ 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, LocalEngineID) of + {ok, NewS} -> + {noreply, NewS}; + {'EXIT', R} -> + ?vinfo("Trap not sent:~n ~p", [R]), + {noreply, S}; + _ -> + {noreply, S} + end; + +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) of + Recv, Varbinds, LocalEngineID) of {ok, NewS} -> {noreply, NewS}; {'EXIT', R} -> @@ -741,17 +786,18 @@ 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({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} -> @@ -861,17 +907,29 @@ 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)) of + Recv, Varbinds, LocalEngineID)) of {ok, NewS} -> {reply, ok, NewS}; {'EXIT', Reason} -> @@ -881,8 +939,33 @@ handle_call({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, ?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, 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({discovery, - TargetName, Notification, ContextName, Vbs, DiscoHandler, ExtraInfo}, + TargetName, Notification, ContextName, Vbs, DiscoHandler, + ExtraInfo}, From, #state{disco = undefined} = S) -> ?vlog("[handle_call] initiate discovery process:" @@ -1439,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), @@ -1464,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} -> @@ -1623,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: " @@ -1646,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 @@ -1683,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 @@ -1700,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_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. |