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