snmpa_trap.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 809 行 · 第 1/3 页

ERL
809
字号
		{Enterprise,?enterpriseSpecific,Specific}    end,    {value, AgentIp} = snmp_framework_mib:intAgentIpAddress(get),    #trappdu{enterprise = Enterp,	     agent_addr = AgentIp,	     generic_trap = Generic,	     specific_trap = Spec,	     time_stamp = SysUpTime,	     varbinds = VarbindList}.make_v2_notif_pdu(Vbs, Type) ->    #pdu{type = Type,	 request_id = snmpa_mpd:generate_req_id(),	 error_status = noError,	 error_index = 0,	 varbinds = Vbs}.make_varbind_list(Varbinds) ->    {VariablesWithValueAndType, VariablesWithType} =	split_variables(order(Varbinds)),    V = get_all(VariablesWithType),    Vars = lists:append([V, VariablesWithValueAndType]),    [make_varbind(Var) || Var <- unorder(lists:keysort(1, Vars))].%%-----------------------------------------------------------------%% Func: send_trap/6%% Args: TrapRec = #trap | #notification%%       NotifyName = string()%%       ContextName = string()%%       Recv = no_receiver | {Ref, Receiver}%%       Receiver = pid() | atom() | {M,F,A}%%       Vbs = [varbind()]%%       NetIf = pid()%% Purpose: Default trap sending function.%%          Sends the trap to the targets pointed out by NotifyName.%%          If NotifyName is ""; the normal procedure defined in %%          SNMP-NOTIFICATION-MIB is used, i.e. the trap is sent to%%          all managers.%%          Otherwise, the NotifyName is used to find an entry in the%%          SnmpNotifyTable which define how to send the notification%%          (as an Inform or a Trap), and to select targets from%%          SnmpTargetAddrTable (using the Tag).%%-----------------------------------------------------------------send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, NetIf) ->    VarbindList = make_varbind_list(Vbs),    Dests = find_dests(NotifyName),    send_trap_pdus(Dests, ContextName, {TrapRec, VarbindList}, [], [], [],		   Recv, NetIf).	    get_all(VariablesWithType) ->    {Order, Varbinds} = extract_order(VariablesWithType, 1),    case snmpa_agent:do_get(snmpa_acm:get_root_mib_view(), Varbinds, true) of	{noError, _, NewVarbinds} ->	    contract_order(Order, NewVarbinds);	{ErrorStatus, ErrorIndex, _} ->	    user_err("snmpa_trap: get operation failed {~w, ~w}"		     "~n    in ~w",		     [ErrorStatus, ErrorIndex, Varbinds]),	    throw(error)    end.    make_varbind(Varbind) when record(Varbind, varbind) ->    Varbind;make_varbind({VarOid, ASN1Type, Value}) ->    case snmpa_agent:make_value_a_correct_value(Value, ASN1Type, undef) of	{value, Type, Val} ->	    #varbind{oid = VarOid, variabletype = Type, value = Val};	{error, Reason} -> 	    user_err("snmpa_trap: Invalid value: ~w"		     "~n   Oid:  ~w"		     "~n   Val:  ~w"		     "~n   Type: ~w",		     [Reason, VarOid, Value, ASN1Type]),	    throw(error)    end.order(Varbinds) -> order(Varbinds, 1).order([H | T], No) -> [{No, H} | order(T, No + 1)];order([], _) -> [].unorder([{_No, H} | T]) -> [H | unorder(T)];unorder([]) -> [].extract_order([{No, {VarOid, _Type}} | T], Index) ->    {Order, V} = extract_order(T, Index+1),    {[No | Order], [#varbind{oid = VarOid, org_index = Index} | V]};extract_order([], _) -> {[], []}.contract_order([No | Order], [Varbind | T]) ->    [{No, Varbind} | contract_order(Order, T)];contract_order([], []) -> [].split_variables([{No, {VarOid, Type, Val}} | T]) when list(VarOid) ->    {A, B} = split_variables(T),    {[{No, {VarOid, Type, Val}} | A], B};split_variables([{No, {VarOid, Type}} | T])   when list(VarOid), record(Type, asn1_type) ->    {A, B} = split_variables(T),    {A, [{No, {VarOid, Type}} | B]};split_variables([{_No, {VarName, Value}} | _T]) ->    user_err("snmpa_trap: Undefined variable ~w (~w)", [VarName, Value]),    throw(error);split_variables([{_No, {VarName, RowIndex, Value}} | _T]) ->    user_err("snmpa_trap: Undefined variable ~w ~w (~w)",	     [VarName, RowIndex, Value]),    throw(error);split_variables([]) -> {[], []}.%%-----------------------------------------------------------------%% Func: find_dests(NotifyName) -> %%          [{DestAddr, TargetName, TargetParams, NotifyType}]%% Types: NotifyType = string()%%        DestAddr = {TDomain, TAddr}%%        TargetName = string()%%        TargetParams = {MpModel, SecModel, SecName, SecLevel}%%        NotifyType = trap | {inform, Timeout, Retry}%% Returns: A list of all Destination addresses for this community.%% NOTE: This function is executed in the master agent's context%%-----------------------------------------------------------------find_dests("") ->    snmp_notification_mib:get_targets();find_dests(NotifyName) ->    case snmp_notification_mib:get_targets(NotifyName) of	[] ->	    ?vlog("No dests found for snmpNotifyName: ~p",[NotifyName]),	    [];	Dests ->	    Dests    end.%%-----------------------------------------------------------------%% NOTE: This function is executed in the master agent's context%% For each target, check if it has access to the objects in the%% notification, determine which message version (v1, v2c or v3)%% should be used for the target, and determine the message%% specific parameters to be used.%%-----------------------------------------------------------------send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel},		 Type} | T],	       ContextName,{TrapRec, Vbs}, V1Res, V2Res, V3Res, Recv, NetIf) ->    ?vdebug("send trap pdus: "	    "~n   Destination address: ~p"	    "~n   Target name:         ~p"	    "~n   MP model:            ~p"	    "~n   Type:                ~p"	    "~n   V1Res:               ~p"	    "~n   V2Res:               ~p"	    "~n   V3Res:               ~p",	    [DestAddr,TargetName,MpModel,Type,V1Res,V2Res,V3Res]),    case snmpa_vacm:get_mib_view(notify, SecModel, SecName, SecLevel,				 ContextName) of	{ok, MibView} ->	    case check_all_varbinds(TrapRec, Vbs, MibView) of		true when MpModel == ?MP_V1 ->		    ?vtrace("v1 mp model",[]),		    ContextEngineId = snmp_framework_mib:get_engine_id(),		    case snmp_community_mib:vacm2community({SecName,							    ContextEngineId,							    ContextName},							   DestAddr) of			{ok, Community} ->			    ?vdebug("community found  for v1 dest: ~p",				    [element(2, DestAddr)]),			    send_trap_pdus(T, ContextName, {TrapRec, Vbs},					   [{DestAddr, Community} | V1Res],					   V2Res, V3Res, Recv, 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)		    end;		true when MpModel == ?MP_V2C ->		    ?vtrace("v2c mp model",[]),		    ContextEngineId = snmp_framework_mib:get_engine_id(),		    case snmp_community_mib:vacm2community({SecName,							    ContextEngineId,							    ContextName},							   DestAddr) of			{ok, Community} ->			    ?vdebug("community found for v2c dest: ~p", 				    [element(2, DestAddr)]),			    send_trap_pdus(T, ContextName, {TrapRec, Vbs},					   V1Res,					   [{DestAddr, Community, Type}|V2Res],					   V3Res, Recv, 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)		    end;		true when MpModel == ?MP_V3 ->		    ?vtrace("v3 mp model",[]),		    SecLevelF = mk_flag(SecLevel),		    MsgData = {SecModel, SecName, SecLevelF, TargetName},		    send_trap_pdus(T, ContextName, {TrapRec, Vbs},				   V1Res, V2Res,				   [{DestAddr, MsgData, Type} | V3Res],				   Recv, 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);		_ ->		    ?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)	    end;	{discarded, Reason} ->	    ?vlog("mib view error ~p for"		  "~n   dest:    ~p"		  "~n   SecName: ~w", 		  [Reason, element(2, DestAddr), SecName]),	    send_trap_pdus(T, ContextName, {TrapRec, Vbs},			   V1Res, V2Res, V3Res, Recv, NetIf)    end;send_trap_pdus([], ContextName, {TrapRec, Vbs}, V1Res, V2Res, V3Res,	       Recv, NetIf) ->    SysUpTime = snmp_standard_mib:sys_up_time(),    ?vdebug("send trap pdus with sysUpTime ~p",[SysUpTime]),    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_v1_trap(_TrapRec, [], _Vbs, _NetIf, _SysUpTime) ->    ok;send_v1_trap(#trap{enterpriseoid = Enter, specificcode = Spec},	     V1Res, Vbs, NetIf, SysUpTime) ->    ?vdebug("prepare to send v1 trap "	    "~n   '~p'"	    "~n   with"	    "~n   ~p"	    "~n   to"	    "~n   ~p",[Enter,Spec,V1Res]),    TrapPdu = make_v1_trap_pdu(Enter, Spec, Vbs, SysUpTime),    AddrCommunities = mk_addr_communities(V1Res),    lists:foreach(fun({Community, Addrs}) ->			  ?vtrace("send v1 trap pdu to ~p",[Addrs]),			  NetIf ! {send_pdu, 'version-1', TrapPdu,				   {community, Community}, Addrs}		  end, AddrCommunities);send_v1_trap(#notification{oid = Oid}, V1Res, Vbs, NetIf, SysUpTime) ->    %% Use alg. in rfc2089 to map a v2 trap to a v1 trap    % delete Counter64 objects from vbs    ?vdebug("prepare to send v1 trap '~p'",[Oid]),    NVbs = lists:filter(fun(Vb) when Vb#varbind.variabletype =/= 'Counter64' ->				true;			   (_) -> false			end, Vbs),    {Enter,Spec} = 	case Oid of	    [1,3,6,1,6,3,1,1,5,Specific] ->		{?snmp,Specific - 1};	    _ ->		case lists:reverse(Oid) of		    [Last, 0 | First] ->			{lists:reverse(First),Last};		    [Last | First] ->			{lists:reverse(First),Last}		end	end,    TrapPdu = make_v1_trap_pdu(Enter, Spec, NVbs, SysUpTime),    AddrCommunities = mk_addr_communities(V1Res),    lists:foreach(fun({Community, Addrs}) ->			  ?vtrace("send v1 trap to ~p",[Addrs]),			  NetIf ! {send_pdu, 'version-1', TrapPdu,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?