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 + -
显示快捷键?