snmpa_trap.erl

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

ERL
809
字号
				   {community, Community}, Addrs}		  end, AddrCommunities).    send_v2_trap(_TrapRec, [], _Vbs, _Recv, _NetIf, _SysUpTime) ->    ok;send_v2_trap(TrapRec, V2Res, Vbs, Recv, NetIf, SysUpTime) ->    ?vdebug("prepare to send v2 trap",[]),    {_Oid, IVbs} = mk_v2_trap(TrapRec, Vbs, SysUpTime),    TrapRecvs = get_trap_recvs(V2Res),    InformRecvs = get_inform_recvs(V2Res),    do_send_v2_trap(TrapRecvs, IVbs, NetIf),    do_send_v2_inform(InformRecvs, IVbs, Recv, NetIf).    send_v3_trap(_TrapRec, [], _Vbs, _Recv, _NetIf, _SysUpTime, _ContextName) ->    ok;send_v3_trap(TrapRec, V3Res, Vbs, Recv, 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    InformRecvs = get_inform_recvs(V3Res),    do_send_v3_trap(TrapRecvs, ContextName, IVbs, NetIf),    do_send_v3_inform(InformRecvs, ContextName, IVbs, Recv, 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) ->    %% 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} = 	case Enter of	    ?snmp ->		{?snmpTraps ++ [Spec + 1],sys_object_id()};	    _ ->		{Enter ++ [0, Spec],Enter}	end,    ExtraVb = #varbind{oid = ?snmpTrapEnterprise_instance,		       variabletype = 'OBJECT IDENTIFIER',		       value = Enterp},    mk_v2_notif(Oid, Vbs ++ [ExtraVb], SysUpTime).    mk_v2_notif(Oid, Vbs, SysUpTime) ->    IVbs = [#varbind{oid = ?sysUpTime_instance,		     variabletype = 'TimeTicks',		     value = SysUpTime},	    #varbind{oid = ?snmpTrapOID_instance,		     variabletype = 'OBJECT IDENTIFIER',		     value = Oid} | Vbs],    {Oid, IVbs}.%% Addr = {Domain, DomainAddr} ; e.g. {snmpUDPDomain, {IPasList, Udp}}%% MsgData = CommunityString (v1, v2c) |%%           {SecModel, SecName, SecLevel, TargetAddrName} (v3)get_trap_recvs([{Addr, MsgData, trap} | T]) ->    [{Addr, MsgData} | get_trap_recvs(T)];get_trap_recvs([_ | T]) ->    get_trap_recvs(T);get_trap_recvs([]) ->    [].get_inform_recvs([{Addr, MsgData, {inform, Timeout, Retry}} | T]) ->    [{Addr, MsgData, Timeout, Retry} | get_inform_recvs(T)];get_inform_recvs([_ | T]) ->    get_inform_recvs(T);get_inform_recvs([]) ->    [].do_send_v2_trap([], _Vbs, _NetIf) ->    ok;do_send_v2_trap(Recvs, Vbs, NetIf) ->    TrapPdu = make_v2_notif_pdu(Vbs, 'snmpv2-trap'),    AddrCommunities = mk_addr_communities(Recvs),    lists:foreach(fun({Community, Addrs}) ->			  ?vtrace("~n   send v2 trap to ~p",[Addrs]),			  NetIf ! {send_pdu, 'version-2', TrapPdu,				   {community, Community}, Addrs}		  end, AddrCommunities),    ok.do_send_v2_inform([], _Vbs, Recv, _NetIf) ->    deliver_recv(Recv, snmp_targets, []);do_send_v2_inform(Recvs, Vbs, Recv, NetIf) ->    Targets = lists:map(fun({Addr, _Community, _Timeout, _Retry}) ->				Addr			end, Recvs),    deliver_recv(Recv, snmp_targets, Targets),    lists:foreach(      fun({Addr, Community, Timeout, Retry}) ->	      ?vtrace("~n   start inform sender to send v2 inform to ~p",		      [Addr]),	      proc_lib:spawn_link(?MODULE, init_v2_inform,				  [Addr, Timeout, Retry, Vbs,				   Recv, NetIf, Community,				   get(verbosity),get(sname)])      end,       Recvs).do_send_v3_trap([], _ContextName, _Vbs, _NetIf) ->    ok;do_send_v3_trap(Recvs, ContextName, Vbs, NetIf) ->    TrapPdu = make_v2_notif_pdu(Vbs, 'snmpv2-trap'), % Yes, v2    ContextEngineId = snmp_framework_mib:get_engine_id(),    lists:foreach(fun(Recv) ->			  ?vtrace("~n   send v3 notif to ~p",[Recv]),			  NetIf ! {send_pdu, 'version-3', TrapPdu,				   {v3, ContextEngineId, ContextName}, [Recv]}		  end, Recvs),    ok.do_send_v3_inform([], _ContextName, _Vbs, Recv, _NetIf) ->    deliver_recv(Recv, snmp_targets, []);do_send_v3_inform(Recvs, ContextName, Vbs, Recv, NetIf) ->    Targets = lists:map(fun({Addr, _, _, _}) -> Addr end, Recvs),    deliver_recv(Recv, snmp_targets, Targets),    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,				   get(verbosity),get(sname)])      end,       Recvs).%% New processinit_v2_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, Community,V,S) ->    %% Make a new Inform for each recipient; they need unique    %% request-ids!    put(verbosity,V),    put(sname,inform_sender_short_name(S)),    ?vdebug("~n   starting with timeout = ~p and retry = ~p",	    [Timeout,Retry]),    InformPdu = make_v2_notif_pdu(Vbs, 'inform-request'),    Msg = {send_pdu_req, 'version-2', InformPdu, {community, Community},	   [Addr], self()},    send_inform(Addr, Timeout*10, Retry, Msg, Recv, NetIf).    send_inform(Addr, _Timeout, -1, _Msg,  Recv, _NetIf) ->    ?vinfo("~n   Delivery of send-pdu-request to net-if failed: reply timeout",	   []),    deliver_recv(Recv, snmp_notification, {no_response, Addr});send_inform(Addr, Timeout, Retry, Msg, Recv, NetIf) ->    ?vtrace("~n   deliver send-pdu-request to net-if when"	    "~n   Timeout: ~p"	    "~n   Retry:   ~p",[Timeout, Retry]),    NetIf ! Msg,    receive	{snmp_response_received, _Vsn, _Pdu, _From} ->	    ?vtrace("~n   received response for ~p (~p)",[Recv,Retry]),	    deliver_recv(Recv, snmp_notification, {got_response, Addr})    after	Timeout ->	    send_inform(Addr, Timeout*2, Retry-1, Msg, Recv, NetIf)    end.%% New processinit_v3_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, ContextName,V,S) ->    %% Make a new Inform for each recipient; they need unique    %% request-ids!    put(verbosity,V),    put(sname,inform_sender_short_name(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(),    Msg = {send_pdu_req, 'version-3', InformPdu,	   {v3, ContextEngineId, ContextName}, [Addr], self()},    send_inform(Addr, Timeout*10, Retry, Msg, Recv, NetIf).% A nasty bit of verbosity setup...    inform_sender_short_name(ma)   -> mais;inform_sender_short_name(maw)  -> mais;inform_sender_short_name(mats) -> mais;inform_sender_short_name(_)    -> sais.deliver_recv(no_receiver, _MsgId, _Result) ->    ?vtrace("deliver_recv -> no receiver", []),    ok;deliver_recv({Tag, Receiver}, MsgId, Result) ->    ?vtrace("deliver_recv -> entry with"	"~n   Tag:      ~p"	"~n   Receiver: ~p"	"~n   MsgId:    ~p"	"~n   Result:   ~p"	"", [Tag, Receiver, MsgId, Result]),    Msg = {MsgId, Tag, Result},    case Receiver of	Pid when pid(Pid) ->	    Pid ! Msg;	Name when atom(Name) ->	    catch Name ! Msg;	{M, F, A} ->	    catch M:F([Msg | A]);	Else ->	    ?vinfo("~n   Cannot deliver acknowledgment: bad receiver = '~p'",		   [Else]),	    user_err("snmpa: bad receiver, ~w\n", [Else])    end;deliver_recv(Else, _MsgId, _Result) ->    ?vinfo("~n   Cannot deliver acknowledgment: bad receiver = '~p'",	   [Else]),    user_err("snmpa: bad receiver, ~w\n", [Else]).check_all_varbinds(#notification{oid = Oid}, Vbs, MibView) ->    case snmpa_acm:validate_mib_view(Oid, MibView) of	true -> check_all_varbinds(Vbs, MibView);	false -> false    end;check_all_varbinds(#trap{enterpriseoid = Enter, specificcode = Spec},		   Vbs, MibView) ->    %% Use alg. in rfc1908 to map a v1 trap to a v2 trap    Oid = case Enter of	      ?snmp -> ?snmpTraps ++ [Spec + 1];	      _ -> Enter ++ [0, Spec]	  end,    case snmpa_acm:validate_mib_view(Oid, MibView) of	true -> check_all_varbinds(Vbs, MibView);	false -> false    end.check_all_varbinds([#varbind{oid = Oid} | Vbs], MibView) ->    case snmpa_acm:validate_mib_view(Oid, MibView) of	true -> check_all_varbinds(Vbs, MibView);	false -> false    end;check_all_varbinds([], _MibView) -> true.%%--------------------------------------------------%% Functions to access the local mib.%%--------------------------------------------------sys_object_id() ->    case snmpa_agent:do_get(snmpa_acm:get_root_mib_view(),			    [#varbind{oid = ?sysObjectID_instance}],			    true) of	{noError, _, [#varbind{value = Value}]} ->	    Value;	X ->	    user_err("sysObjectID bad return value ~w", [X])    end.%% Collect all ADDRs for each community together.%% In: [{Addr, Community}]%% Out: [{Community, [Addr]}]mk_addr_communities(Recvs) ->    [{Addr, Comm} | T] = lists:keysort(2, Recvs),    mic(T, Comm, [Addr], []).mic([{Addr, Comm} | T], CurComm, AddrList, Res) when Comm == CurComm ->    mic(T, CurComm, [Addr | AddrList], Res);mic([{Addr, Comm} | T], CurComm, AddrList, Res) ->    mic(T, Comm, [Addr], [{CurComm, AddrList} | Res]);mic([], CurComm, AddrList, Res) ->    [{CurComm, AddrList} | Res].%%-----------------------------------------------------------------%% Convert the SecurityLevel into a flag value used by snmpa_mpd%%-----------------------------------------------------------------mk_flag(?'SnmpSecurityLevel_noAuthNoPriv') -> 0;mk_flag(?'SnmpSecurityLevel_authNoPriv') -> 1;mk_flag(?'SnmpSecurityLevel_authPriv') -> 3.     user_err(F, A) ->    snmpa_error:user_err(F, A).

⌨️ 快捷键说明

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