diff options
Diffstat (limited to 'lib/snmp/src/agent')
24 files changed, 1760 insertions, 450 deletions
diff --git a/lib/snmp/src/agent/snmp_community_mib.erl b/lib/snmp/src/agent/snmp_community_mib.erl index a2ee7bf0c9..77307aa7ad 100644 --- a/lib/snmp/src/agent/snmp_community_mib.erl +++ b/lib/snmp/src/agent/snmp_community_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% Copyright Ericsson AB 1999-2011. 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 @@ -18,12 +18,14 @@ %% -module(snmp_community_mib). +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). -export([configure/1, reconfigure/1, snmpCommunityTable/1, snmpCommunityTable/3, snmpTargetAddrExtTable/3, community2vacm/2, vacm2community/2, get_target_addr_ext_mms/2]). --export([add_community/5, delete_community/1]). +-export([add_community/5, add_community/6, delete_community/1]). -export([check_community/1]). -include("SNMP-COMMUNITY-MIB.hrl"). @@ -126,12 +128,16 @@ read_community_config_files(Dir) -> Comms. check_community({Index, CommunityName, SecName, CtxName, TransportTag}) -> + EngineID = get_engine_id(), + check_community({Index, CommunityName, SecName, + EngineID, CtxName, TransportTag}); +check_community({Index, CommunityName, SecName, + EngineID, CtxName, TransportTag}) -> snmp_conf:check_string(Index,{gt,0}), snmp_conf:check_string(CommunityName), snmp_conf:check_string(SecName), snmp_conf:check_string(CtxName), snmp_conf:check_string(TransportTag), - EngineID = get_engine_id(), Comm = {Index, CommunityName, SecName, EngineID, CtxName, TransportTag, ?'StorageType_nonVolatile', ?'RowStatus_active'}, {ok, Comm}; @@ -171,6 +177,13 @@ table_del_row(Tab, Key) -> %% FIXME: does not work with mnesia add_community(Idx, CommName, SecName, CtxName, TransportTag) -> Community = {Idx, CommName, SecName, CtxName, TransportTag}, + do_add_community(Community). + +add_community(Idx, CommName, SecName, EngineId, CtxName, TransportTag) -> + Community = {Idx, CommName, SecName, EngineId, CtxName, TransportTag}, + do_add_community(Community). + +do_add_community(Community) -> case (catch check_community(Community)) of {ok, Row} -> Key = element(1, Row), @@ -334,6 +347,8 @@ get_target_addr_ext_mms(TDomain, TAddress, Key) -> get_target_addr_ext_mms(TDomain, TAddress, NextKey) end end. + + %%----------------------------------------------------------------- %% Instrumentation Functions %%----------------------------------------------------------------- @@ -345,7 +360,7 @@ snmpCommunityTable(print) -> PrintRow = fun(Prefix, Row) -> lists:flatten( - io_lib:format("~sIndex: ~p" + io_lib:format("~sIndex: ~p" "~n~sName: ~p" "~n~sSecurityName: ~p" "~n~sContextEngineID: ~p" diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl index 0916e2ec74..0d7866d94d 100644 --- a/lib/snmp/src/agent/snmp_framework_mib.erl +++ b/lib/snmp/src/agent/snmp_framework_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% Copyright Ericsson AB 1999-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 @@ -37,6 +37,8 @@ %%% over all known contexts. %%%----------------------------------------------------------------- %% External exports +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). -export([init/0, configure/1]). -export([intContextTable/1, intContextTable/3, intAgentUDPPort/1, intAgentIpAddress/1, @@ -371,15 +373,27 @@ intAgentUDPPort(Op) -> intAgentIpAddress(Op) -> snmp_generic:variable_func(Op, db(intAgentIpAddress)). +snmpEngineID(print) -> + VarAndValue = [{snmpEngineID, snmpEngineID(get)}], + snmpa_mib_lib:print_variables(VarAndValue); snmpEngineID(Op) -> snmp_generic:variable_func(Op, db(snmpEngineID)). +snmpEngineMaxMessageSize(print) -> + VarAndValue = [{snmpEngineMaxMessageSize, snmpEngineMaxMessageSize(get)}], + snmpa_mib_lib:print_variables(VarAndValue); snmpEngineMaxMessageSize(Op) -> snmp_generic:variable_func(Op, db(snmpEngineMaxMessageSize)). +snmpEngineBoots(print) -> + VarAndValue = [{snmpEngineBoots, snmpEngineBoots(get)}], + snmpa_mib_lib:print_variables(VarAndValue); snmpEngineBoots(Op) -> snmp_generic:variable_func(Op, db(snmpEngineBoots)). +snmpEngineTime(print) -> + VarAndValue = [{snmpEngineTime, snmpEngineTime(get)}], + snmpa_mib_lib:print_variables(VarAndValue); snmpEngineTime(get) -> {value, get_engine_time()}. diff --git a/lib/snmp/src/agent/snmp_generic.erl b/lib/snmp/src/agent/snmp_generic.erl index 508aa090d9..06afa68d96 100644 --- a/lib/snmp/src/agent/snmp_generic.erl +++ b/lib/snmp/src/agent/snmp_generic.erl @@ -1,7 +1,7 @@ %% %% %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 @@ -18,6 +18,8 @@ %% -module(snmp_generic). +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). -export([variable_func/2, variable_func/3, variable_get/1, variable_set/2]). -export([table_func/2, table_func/4, table_set_row/5, table_set_cols/3, table_set_cols/4, diff --git a/lib/snmp/src/agent/snmp_generic_mnesia.erl b/lib/snmp/src/agent/snmp_generic_mnesia.erl index a73aad5b33..ce42af404b 100644 --- a/lib/snmp/src/agent/snmp_generic_mnesia.erl +++ b/lib/snmp/src/agent/snmp_generic_mnesia.erl @@ -121,7 +121,7 @@ table_func(set, RowIndex, Cols, Name) -> fun() -> snmp_generic:table_set_row( {Name, mnesia}, nofunc, - {snmp_generic_mnesia, table_try_make_consistent}, + fun table_try_make_consistent/2, RowIndex, Cols) end) of {atomic, Value} -> @@ -368,7 +368,8 @@ table_set_elements(Name, RowIndex, Cols) -> _ -> false end. table_set_elements(Name, RowIndex, Cols, ConsFunc) -> - #table_info{index_types = Indexes, first_own_index = FirstOwnIndex} = + #table_info{index_types = Indexes, + first_own_index = FirstOwnIndex} = snmp_generic:table_info(Name), AddCol = if FirstOwnIndex == 0 -> 2; diff --git a/lib/snmp/src/agent/snmp_notification_mib.erl b/lib/snmp/src/agent/snmp_notification_mib.erl index 16e43f05d7..720ac749b8 100644 --- a/lib/snmp/src/agent/snmp_notification_mib.erl +++ b/lib/snmp/src/agent/snmp_notification_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2011. 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 @@ -18,6 +18,8 @@ %% -module(snmp_notification_mib). +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). -export([configure/1, reconfigure/1, invalidate_cache/0, snmpNotifyTable/1, snmpNotifyTable/3, snmpNotifyFilterTable/3, snmpNotifyFilterProfileTable/3, @@ -271,9 +273,12 @@ find_targets(Key, TargAddrs, Db, Res) -> get_targets([{TagList, Addr, TargetName, Params, Timeout, Retry}|T], Tag, Type, Name) -> case snmp_misc:is_tag_member(Tag, TagList) of - true -> [{Name, {Addr, TargetName, Params, type(Type, Timeout, Retry)}}| - get_targets(T, Tag, Type, Name)]; + true -> + ?vtrace("tag ~w *is* member", [Tag]), + [{Name, {Addr, TargetName, Params, type(Type, Timeout, Retry)}}| + get_targets(T, Tag, Type, Name)]; false -> + ?vtrace("tag ~w is *not* member", [Tag]), get_targets(T, Tag, Type, Name) end; get_targets([], _Tag, _Type, _Name) -> diff --git a/lib/snmp/src/agent/snmp_standard_mib.erl b/lib/snmp/src/agent/snmp_standard_mib.erl index 3928a8afe6..b6834d278c 100644 --- a/lib/snmp/src/agent/snmp_standard_mib.erl +++ b/lib/snmp/src/agent/snmp_standard_mib.erl @@ -1,7 +1,7 @@ %% %% %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 @@ -33,11 +33,35 @@ -define(disabled, 2). %% External exports +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). -export([configure/1, reconfigure/1, reset/0, sys_up_time/0, sys_up_time/1, snmp_enable_authen_traps/1, snmp_enable_authen_traps/2, sys_object_id/1, sys_object_id/2, sys_or_table/3, variable_func/1, variable_func/2, inc/1, inc/2]). +-export([sysDescr/1, sysContact/1, sysName/1, sysLocation/1, + sysServices/1, sysUpTime/1, snmpEnableAuthenTraps/1, + sysObjectID/1, + snmpInPkts/1, snmpOutPkts/1, + snmpInBadVersions/1, + snmpInBadCommunityNames/1, snmpInBadCommunityUses/1, + snmpInASNParseErrs/1, + snmpInTooBigs/1, + snmpInNoSuchNames/1, snmpInBadValues/1, + snmpInReadOnlys/1, snmpInGenErrs/1, + snmpInTotalReqVars/1, snmpInTotalSetVars/1, + snmpInGetRequests/1, snmpInSetRequests/1, + snmpInGetNexts/1, + snmpInGetResponses/1, snmpInTraps/1, + snmpOutTooBigs/1, + snmpOutNoSuchNames/1, + snmpOutBadValues/1, + snmpOutGenErrs/1, + snmpOutGetRequests/1, snmpOutSetRequests/1, + snmpOutGetNexts/1, + snmpOutGetResponses/1, + snmpOutTraps/1]). -export([dummy/1, snmp_set_serial_no/1, snmp_set_serial_no/2]). -export([add_agent_caps/2, del_agent_caps/1, get_agent_caps/0]). -export([check_standard/1]). @@ -200,18 +224,257 @@ variable_func(get, Name) -> inc(Name) -> inc(Name, 1). inc(Name, N) -> ets:update_counter(snmp_agent_table, Name, N). + +sysDescr(print) -> + VarAndValue = [{sysDescr, sysDescr(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + +sysDescr(get) -> + VarDB = db(sysDescr), + snmp_generic:variable_get(VarDB). + + +sysContact(print) -> + VarAndValue = [{sysContact, sysContact(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + +sysContact(get) -> + VarDB = db(sysContact), + snmp_generic:variable_get(VarDB). + + +sysName(print) -> + VarAndValue = [{sysName, sysName(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + +sysName(get) -> + VarDB = db(sysName), + snmp_generic:variable_get(VarDB). + + +sysLocation(print) -> + VarAndValue = [{sysLocation, sysLocation(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + +sysLocation(get) -> + VarDB = db(sysLocation), + snmp_generic:variable_get(VarDB). + + +sysServices(print) -> + VarAndValue = [{sysServices, sysServices(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + +sysServices(get) -> + VarDB = db(sysServices), + snmp_generic:variable_get(VarDB). + + +snmpInPkts(print) -> + gen_counter(print, snmpInPkts); +snmpInPkts(get) -> + gen_counter(get, snmpInPkts). + + +snmpOutPkts(print) -> + gen_counter(print, snmpOutPkts); +snmpOutPkts(get) -> + gen_counter(get, snmpOutPkts). + + +snmpInASNParseErrs(print) -> + gen_counter(print, snmpInASNParseErrs); +snmpInASNParseErrs(get) -> + gen_counter(get, snmpInASNParseErrs). + + +snmpInBadCommunityNames(print) -> + gen_counter(print, snmpInBadCommunityNames); +snmpInBadCommunityNames(get) -> + gen_counter(get, snmpInBadCommunityNames). + + +snmpInBadCommunityUses(print) -> + gen_counter(print, snmpInBadCommunityUses); + +snmpInBadCommunityUses(get) -> + gen_counter(get, snmpInBadCommunityUses). + + +snmpInBadVersions(print) -> + gen_counter(print, snmpInBadVersions); +snmpInBadVersions(get) -> + gen_counter(get, snmpInBadVersions). + + +snmpInTooBigs(print) -> + gen_counter(print, snmpInTooBigs); +snmpInTooBigs(get) -> + gen_counter(get, snmpInTooBigs). + + +snmpInNoSuchNames(print) -> + gen_counter(print, snmpInNoSuchNames); +snmpInNoSuchNames(get) -> + gen_counter(get, snmpInNoSuchNames). + + +snmpInBadValues(print) -> + gen_counter(print, snmpInBadValues); +snmpInBadValues(get) -> + gen_counter(get, snmpInBadValues). + + +snmpInReadOnlys(print) -> + gen_counter(print, snmpInReadOnlys); +snmpInReadOnlys(get) -> + gen_counter(get, snmpInReadOnlys). + + +snmpInGenErrs(print) -> + gen_counter(print, snmpInGenErrs); +snmpInGenErrs(get) -> + gen_counter(get, snmpInGenErrs). + + +snmpInTotalReqVars(print) -> + gen_counter(print, snmpInTotalReqVars); +snmpInTotalReqVars(get) -> + gen_counter(get, snmpInTotalReqVars). + + +snmpInTotalSetVars(print) -> + gen_counter(print, snmpInTotalSetVars); +snmpInTotalSetVars(get) -> + gen_counter(get, snmpInTotalSetVars). + + +snmpInGetRequests(print) -> + gen_counter(print, snmpInGetRequests); +snmpInGetRequests(get) -> + gen_counter(get, snmpInGetRequests). + + +snmpInSetRequests(print) -> + gen_counter(print, snmpInSetRequests); +snmpInSetRequests(get) -> + gen_counter(get, snmpInSetRequests). + + +snmpInGetNexts(print) -> + gen_counter(print, snmpInGetNexts); +snmpInGetNexts(get) -> + gen_counter(get, snmpInGetNexts). + + +snmpInGetResponses(print) -> + gen_counter(print, snmpInGetResponses); +snmpInGetResponses(get) -> + gen_counter(get, snmpInGetResponses). + + +snmpInTraps(print) -> + gen_counter(print, snmpInTraps); +snmpInTraps(get) -> + gen_counter(get, snmpInTraps). + + +snmpOutTooBigs(print) -> + gen_counter(print, snmpOutTooBigs); +snmpOutTooBigs(get) -> + gen_counter(get, snmpOutTooBigs). + + +snmpOutNoSuchNames(print) -> + gen_counter(print, snmpOutNoSuchNames); +snmpOutNoSuchNames(get) -> + gen_counter(get, snmpOutNoSuchNames). + + +snmpOutBadValues(print) -> + gen_counter(print, snmpOutBadValues); +snmpOutBadValues(get) -> + gen_counter(get, snmpOutBadValues). + + +snmpOutGenErrs(print) -> + gen_counter(print, snmpOutGenErrs); +snmpOutGenErrs(get) -> + gen_counter(get, snmpOutGenErrs). + + +snmpOutGetRequests(print) -> + gen_counter(print, snmpOutGetRequests); +snmpOutGetRequests(get) -> + gen_counter(get, snmpOutGetRequests). + + +snmpOutSetRequests(print) -> + gen_counter(print, snmpOutSetRequests); +snmpOutSetRequests(get) -> + gen_counter(get, snmpOutSetRequests). + + +snmpOutGetNexts(print) -> + gen_counter(print, snmpOutGetNexts); +snmpOutGetNexts(get) -> + gen_counter(get, snmpOutGetNexts). + + +snmpOutGetResponses(print) -> + gen_counter(print, snmpOutGetResponses); +snmpOutGetResponses(get) -> + gen_counter(get, snmpOutGetResponses). + + +snmpOutTraps(print) -> + gen_counter(print, snmpOutTraps); +snmpOutTraps(get) -> + gen_counter(get, snmpOutTraps). + + +gen_counter(print, Counter) -> + Val = gen_counter(get, Counter), + VarAndValue = [{Counter, Val}], + snmpa_mib_lib:print_variables(VarAndValue); + +gen_counter(get, Counter) -> + variable_func(get, Counter). + + %%----------------------------------------------------------------- %% This is the instrumentation function for sysUpTime. %%----------------------------------------------------------------- +sysUpTime(print) -> + sys_up_time(print); +sysUpTime(get) -> + sys_up_time(get). + sys_up_time() -> snmpa:sys_up_time(). +sys_up_time(print) -> + VarAndValue = [{sysUpTime, sys_up_time(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + sys_up_time(get) -> {value, snmpa:sys_up_time()}. + %%----------------------------------------------------------------- %% This is the instrumentation function for snmpEnableAuthenTraps %%----------------------------------------------------------------- + +snmpEnableAuthenTraps(print) -> + snmp_enable_authen_traps(print); +snmpEnableAuthenTraps(get) -> + snmp_enable_authen_traps(get). + + +snmp_enable_authen_traps(print) -> + VarAndValue = [{snmpEnableAuthenTraps, snmp_enable_authen_traps(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + snmp_enable_authen_traps(new) -> snmp_generic:variable_func(new, db(snmpEnableAuthenTraps)); @@ -224,9 +487,19 @@ snmp_enable_authen_traps(get) -> snmp_enable_authen_traps(set, NewVal) -> snmp_generic:variable_func(set, NewVal, db(snmpEnableAuthenTraps)). + %%----------------------------------------------------------------- -%% This is the instrumentation function for sysObjectId +%% This is the instrumentation function for sysObjectID %%----------------------------------------------------------------- +sysObjectID(print) -> + sys_object_id(print); +sysObjectID(get) -> + sys_object_id(get). + +sys_object_id(print) -> + VarAndValue = [{sysObjectID, sys_object_id(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + sys_object_id(new) -> snmp_generic:variable_func(new, db(sysObjectID)); @@ -239,6 +512,7 @@ sys_object_id(get) -> sys_object_id(set, NewVal) -> snmp_generic:variable_func(set, NewVal, db(sysObjectID)). + %%----------------------------------------------------------------- %% This is a dummy instrumentation function for objects like %% snmpTrapOID, that is accessible-for-notify, with different @@ -247,6 +521,7 @@ sys_object_id(set, NewVal) -> %%----------------------------------------------------------------- dummy(_Op) -> ok. + %%----------------------------------------------------------------- %% This is the instrumentation function for snmpSetSerialNo. %% It is always volatile. diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl index d5c4ec2578..a45db89c09 100644 --- a/lib/snmp/src/agent/snmp_target_mib.erl +++ b/lib/snmp/src/agent/snmp_target_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2011. 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 @@ -18,22 +18,26 @@ %% -module(snmp_target_mib). +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). -export([configure/1, reconfigure/1, snmpTargetSpinLock/1, snmpTargetSpinLock/2, snmpTargetAddrTable/1, snmpTargetAddrTable/3, snmpTargetParamsTable/1, snmpTargetParamsTable/3, get_target_addrs/0, get_target_engine_id/1, set_target_engine_id/2, is_valid_tag/3, get/3, table_next/2]). --export([add_addr/10, delete_addr/1, +-export([add_addr/10, add_addr/11, delete_addr/1, add_params/5, delete_params/1]). -export([check_target_addr/1, check_target_params/1]). +-export([default_domain/0]). --include("snmp_types.hrl"). --include("snmp_tables.hrl"). --include("SNMP-TARGET-MIB.hrl"). --include("SNMPv2-TC.hrl"). --include("SNMPv2-TM.hrl"). --include("SNMP-FRAMEWORK-MIB.hrl"). +-include_lib("snmp/include/snmp_types.hrl"). +-include_lib("snmp/include/snmp_tables.hrl"). +-include_lib("snmp/include/SNMP-TARGET-MIB.hrl"). +-include_lib("snmp/include/SNMPv2-TC.hrl"). +-include_lib("snmp/include/SNMPv2-TM.hrl"). +-include_lib("snmp/include/SNMP-FRAMEWORK-MIB.hrl"). +-include_lib("snmp/include/TRANSPORT-ADDRESS-MIB.hrl"). -define(VMODULE,"TARGET-MIB"). -include("snmp_verbosity.hrl"). @@ -53,6 +57,12 @@ %%----------------------------------------------------------------- + +default_domain() -> + snmpUDPDomain. + + +%%----------------------------------------------------------------- %% Func: configure/1 %% Args: Dir is the directory where the configuration files are found. %% Purpose: If the tables doesn't exist, this function reads @@ -143,39 +153,51 @@ read_target_config_files(Dir) -> %% {Name, Ip, Udp, Timeout, RetryCount, TagList, Params, EngineId, %% TMask, MMS} %%----------------------------------------------------------------- -check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, - Params, EngineId, TMask, MMS}) -> + +check_target_addr({Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, + Params, EngineId, TMask, MMS}) -> ?vtrace("check target address with:" - "~n Name: ~s" - "~n Ip: ~p" - "~n Udp: ~p" - "~n Timeout: ~p" - "~n RetryCount: ~p" - "~n TagList: ~p" - "~n Params: ~p" - "~n EngineId: ~p" - "~n TMask: ~p" - "~n MMS: ~p", - [Name,Ip,Udp,Timeout,RetryCount, - TagList,Params,EngineId,TMask,MMS]), + "~n Name: ~s" + "~n Domain: ~p" + "~n Ip: ~p" + "~n Udp: ~p" + "~n Timeout: ~p" + "~n RetryCount: ~p" + "~n TagList: ~p" + "~n Params: ~p" + "~n EngineId: ~p" + "~n TMask: ~p" + "~n MMS: ~p", + [Name, + Domain, Ip, Udp, + Timeout, RetryCount, + TagList, Params, EngineId, TMask, MMS]), snmp_conf:check_string(Name,{gt,0}), - snmp_conf:check_ip(Ip), + snmp_conf:check_domain(Domain), + snmp_conf:check_ip(Domain, Ip), snmp_conf:check_integer(Udp, {gt, 0}), snmp_conf:check_integer(Timeout, {gte, 0}), snmp_conf:check_integer(RetryCount, {gte,0}), snmp_conf:check_string(TagList), snmp_conf:check_string(Params), check_engine_id(EngineId), - TAddr = Ip ++ [Udp div 256, Udp rem 256], - check_mask(TMask, TAddr), + TAddress = snmp_conf:mk_taddress(Domain, Ip, Udp), + TDomain = snmp_conf:mk_tdomain(Domain), + check_tmask(TDomain, TMask, TAddress), snmp_conf:check_packet_size(MMS), ?vtrace("check target address done",[]), - - Addr = {Name, ?snmpUDPDomain, TAddr, Timeout, + Addr = {Name, TDomain, TAddress, Timeout, RetryCount, TagList, Params, ?'StorageType_nonVolatile', ?'RowStatus_active', EngineId, TMask, MMS}, % Values for Augmenting table in SNMP-COMMUNITY-MIB {ok, Addr}; +check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, + Params, EngineId, TMask, MMS}) -> + Domain = default_domain(), + check_target_addr({Name, + Domain, Ip, Udp, + Timeout, RetryCount, TagList, + Params, EngineId, TMask, MMS}); check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, Params, EngineId}) -> check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, @@ -198,12 +220,13 @@ check_engine_id(discovery) -> check_engine_id(EngineId) -> snmp_conf:check_string(EngineId). -check_mask([], _TAddr) -> + +check_tmask(_TDomain, [], _TAddress) -> ok; -check_mask(TMask, TAddr) when length(TMask) == length(TAddr) -> - snmp_conf:check_taddress(TMask); -check_mask(TMask, _TAddr) -> - throw({error, {invalid_mask, TMask}}). +check_tmask(TDomain, TMask, TAddress) when length(TMask) =:= length(TAddress) -> + snmp_conf:check_taddress(TDomain, TMask); +check_tmask(_TDomain, TMask, _TAddr) -> + throw({error, {invalid_tmask, TMask}}). %%----------------------------------------------------------------- @@ -265,7 +288,13 @@ table_del_row(Tab, Key) -> add_addr(Name, Ip, Port, Timeout, Retry, TagList, Params, EngineId, TMask, MMS) -> - Addr = {Name, Ip, Port, Timeout, Retry, TagList, + Domain = default_domain(), + add_addr(Name, Domain, Ip, Port, Timeout, Retry, TagList, + Params, EngineId, TMask, MMS). + +add_addr(Name, Domain, Ip, Port, Timeout, Retry, TagList, + Params, EngineId, TMask, MMS) -> + Addr = {Name, Domain, Ip, Port, Timeout, Retry, TagList, Params, EngineId, TMask, MMS}, case (catch check_target_addr(Addr)) of {ok, Row} -> @@ -345,8 +374,11 @@ maybe_create_var(Var) -> init_var(Var) -> ets:insert(snmp_agent_table, {Var, 0}). vars() -> - [snmpUnavailableContexts, - snmpUnknownContexts]. + [ + snmpUnavailableContexts, + snmpUnknownContexts + ]. + %%----------------------------------------------------------------- %% API functions @@ -357,10 +389,18 @@ is_valid_tag(Tag, TDomain, TAddress) -> is_valid_tag(TDomain, TAddress, Tag, []). is_valid_tag(TDomain, TAddress, Tag, Key) -> + ?vtrace("is_valid_tag -> entry with" + "~n TDomain: ~p" + "~n TAddress: ~p" + "~n Tag: ~p" + "~n Key: ~p", [TDomain, TAddress, Tag, Key]), case table_next(snmpTargetAddrTable, Key) of endOfTable -> + ?vtrace("is_valid_tag -> endOfTable", []), false; NextKey -> + ?vtrace("is_valid_tag -> next key found" + "~n NextKey: ~p", [NextKey]), case get(snmpTargetAddrTable, NextKey, [?snmpTargetAddrTDomain, ?snmpTargetAddrTAddress, ?snmpTargetAddrTagList, @@ -369,6 +409,8 @@ is_valid_tag(TDomain, TAddress, Tag, Key) -> {value, TAddress}, % RFC2576: chapters 5.2.1 & 5.3 {value, TagList}, {value, []}] -> + ?vtrace("is_valid_tag -> found with exact match" + "~n TagList: ~p", [TagList]), case snmp_misc:is_tag_member(Tag, TagList) of true -> ?vtrace("is_valid_tag -> exact: " @@ -384,9 +426,14 @@ is_valid_tag(TDomain, TAddress, Tag, Key) -> {value, TAddress2}, {value, TagList}, {value, TMask}] when TMask =/= [] -> + ?vtrace("is_valid_tag -> found with exact match" + "~n TagList: ~p" + "~n TMask: ~p", [TagList, TMask]), case snmp_misc:is_tmask_match(TAddress, TAddress2, TMask) of true -> + ?vtrace("is_valid_tag -> " + "tmask match - now check tag member", []), case snmp_misc:is_tag_member(Tag, TagList) of true -> ?vtrace("is_valid_tag -> masked: " @@ -399,10 +446,12 @@ is_valid_tag(TDomain, TAddress, Tag, Key) -> Tag, NextKey) end; false -> + ?vtrace("is_valid_tag -> tmask NO match", []), is_valid_tag(TDomain, TAddress, Tag, NextKey) end; _ -> + ?vtrace("is_valid_tag -> not found - try next", []), is_valid_tag(TDomain, TAddress, Tag, NextKey) end end. @@ -521,6 +570,10 @@ set_target_engine_id(TargetAddrName, EngineId) -> %%----------------------------------------------------------------- %% Instrumentation Functions %%----------------------------------------------------------------- +snmpTargetSpinLock(print) -> + VarAndValue = [{snmpTargetSpinLock, snmpTargetSpinLock(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + snmpTargetSpinLock(new) -> snmp_generic:variable_func(new, {snmpTargetSpinLock, volatile}), {A1,A2,A3} = erlang:now(), @@ -567,7 +620,9 @@ snmpTargetAddrTable(print) -> [Prefix, element(?snmpTargetAddrName, Row), Prefix, element(?snmpTargetAddrTDomain, Row), case element(?snmpTargetAddrTDomain, Row) of - ?snmpUDPDomain -> udp; + ?snmpUDPDomain -> snmpUDPDomain; + ?transportDomainUdpIpv4 -> transportDomainUdpIpv4; + ?transportDomainUdpIpv6 -> transportDomainUdpIpv6; _ -> undefined end, Prefix, element(?snmpTargetAddrTAddress, Row), @@ -601,12 +656,9 @@ snmpTargetAddrTable(print) -> ?'snmpTargetAddrRowStatus_active' -> active; _ -> undefined end, - Prefix, - element(?snmpTargetAddrEngineId, Row), - Prefix, - element(?snmpTargetAddrTMask, Row), - Prefix, - element(?snmpTargetAddrMMS, Row)])) + Prefix, element(?snmpTargetAddrEngineId, Row), + Prefix, element(?snmpTargetAddrTMask, Row), + Prefix, element(?snmpTargetAddrMMS, Row)])) end, snmpa_mib_lib:print_table(Table, DB, FOI, PrintRow); %% Op == new | delete @@ -619,14 +671,14 @@ snmpTargetAddrTable(get, RowIndex, Cols) -> snmpTargetAddrTable(get_next, RowIndex, Cols) -> next(snmpTargetAddrTable, RowIndex, Cols); snmpTargetAddrTable(set, RowIndex, Cols0) -> - %% BMK BMK BMK - case (catch verify_targetAddrTable_cols(Cols0, [])) of + %% BMK BMK + case (catch verify_targetAddrTable_cols(Cols0)) of {ok, Cols} -> snmp_notification_mib:invalidate_cache(), %% Add columns for augmenting table snmpTargetAddrExtTable and for - %% target engine ID. Target engine ID is set to "". The function + %% target engine ID. Target engine ID is set to "". The function %% get_target_engine_id will return "" unless a value is set using - %% set_target_engine_id. If it is "" Informs can't be sent to the + %% set_target_engine_id. If it is "" Informs can't be sent to the %% target. NCols = Cols ++ [{?snmpTargetAddrEngineId, ""}, {?snmpTargetAddrTMask, []}, @@ -637,12 +689,12 @@ snmpTargetAddrTable(set, RowIndex, Cols0) -> Error end; snmpTargetAddrTable(is_set_ok, RowIndex, Cols0) -> - case (catch verify_targetAddrTable_cols(Cols0, [])) of + case (catch verify_targetAddrTable_cols(Cols0)) of {ok, Cols} -> %% Add columns for augmenting table snmpTargetAddrExtTable and for - %% target engine ID. Target engine ID is set to "". The function + %% target engine ID. Target engine ID is set to "". The function %% get_target_engine_id will return "" unless a value is set using - %% set_target_engine_id. If it is "" Informs can't be sent to the + %% set_target_engine_id. If it is "" Informs can't be sent to the %% target. NCols = Cols ++ [{?snmpTargetAddrEngineId, ""}, {?snmpTargetAddrTMask, []}, @@ -656,55 +708,83 @@ snmpTargetAddrTable(Op, Arg1, Arg2) -> Db = db(snmpTargetAddrTable), snmp_generic:table_func(Op, Arg1, Arg2, Db). +verify_targetAddrTable_cols(Cols) -> + ValidCols0 = verify_targetAddrTable_cols(Cols, []), + %% Make a last pass to verify TDomain and TAddress. + ValidCols0. + verify_targetAddrTable_cols([], Cols) -> {ok, lists:reverse(Cols)}; -verify_targetAddrTable_cols([{Col, Val0}|Cols], Acc) -> - Val = verify_targetAddrTable_col(Col, Val0), - verify_targetAddrTable_cols(Cols, [{Col, Val}|Acc]). +verify_targetAddrTable_cols([{Col, Val0}|Cols], ValidCols) -> + Val = verify_targetAddrTable_col(Col, Val0, ValidCols), + verify_targetAddrTable_cols(Cols, [{Col, Val}|ValidCols]). -verify_targetAddrTable_col(?snmpTargetAddrName, Name) -> +verify_targetAddrTable_col(?snmpTargetAddrName, Name, _) -> case (catch snmp_conf:check_string(Name)) of ok -> Name; _ -> wrongValue(?snmpTargetAddrName) end; -verify_targetAddrTable_col(?snmpTargetAddrTAddress, TAddr) -> - case (catch snmp_conf:check_taddress(TAddr)) of +verify_targetAddrTable_col(?snmpTargetAddrTDomain, TDomain, _) -> + case (catch snmp_conf:check_tdomain(TDomain)) of ok -> - TAddr; + TDomain; _ -> - wrongValue(?snmpTargetAddrTAddress) + wrongValue(?snmpTargetAddrTDomain) + end; +%% In order to (properly) validate the TAddress, +%% the TDomain must already have been validated +%% (the format of TAddress depends on TDomain). +verify_targetAddrTable_col(?snmpTargetAddrTAddress, TAddress, ValidCols) -> + case lists:keysearch(?snmpTargetAddrTDomain, 1, ValidCols) of + {value, {?snmpTargetAddrTDomain, TDomain}} -> + case (catch snmp_conf:check_taddress(TDomain, TAddress)) of + ok -> + TAddress; + _ -> + wrongValue(?snmpTargetAddrTAddress) + end; + false -> + %% The user did not provide us with a TDomain, which + %% must mean that he/she intends to use the old domain. + TDomain = snmp_conf:mk_tdomain(default_domain()), + case (catch snmp_conf:check_taddress(TDomain, TAddress)) of + ok -> + TAddress; + _ -> + wrongValue(?snmpTargetAddrTAddress) + end end; -verify_targetAddrTable_col(?snmpTargetAddrTimeout, Timeout) -> +verify_targetAddrTable_col(?snmpTargetAddrTimeout, Timeout, _) -> case (catch snmp_conf:check_integer(Timeout)) of ok when Timeout >= 0 -> Timeout; _ -> wrongValue(?snmpTargetAddrTimeout) end; -verify_targetAddrTable_col(?snmpTargetAddrRetryCount, Retry) -> +verify_targetAddrTable_col(?snmpTargetAddrRetryCount, Retry, _) -> case (catch snmp_conf:check_integer(Retry)) of ok when Retry >= 0 -> Retry; _ -> wrongValue(?snmpTargetAddrRetryCount) end; -verify_targetAddrTable_col(?snmpTargetAddrTagList, TagList) -> +verify_targetAddrTable_col(?snmpTargetAddrTagList, TagList, _) -> case (catch snmp_conf:check_string(TagList)) of ok -> TagList; _ -> wrongValue(?snmpTargetAddrTagList) end; -verify_targetAddrTable_col(?snmpTargetAddrParams, Params) -> +verify_targetAddrTable_col(?snmpTargetAddrParams, Params, _) -> case (catch snmp_conf:check_string(Params)) of ok -> Params; _ -> wrongValue(?snmpTargetAddrParams) end; -verify_targetAddrTable_col(_, Val) -> +verify_targetAddrTable_col(_, Val, _) -> Val. diff --git a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl index 7b881f888c..69cebc858b 100644 --- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl +++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% Copyright Ericsson AB 1999-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 @@ -18,12 +18,20 @@ %% -module(snmp_user_based_sm_mib). +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). -export([configure/1, reconfigure/1, usmUserSpinLock/1, usmUserSpinLock/2, usmUserTable/1, usmUserTable/3, table_next/2, is_engine_id_known/1, get_user/2, get_user_from_security_name/2, mk_key_change/3, mk_key_change/5, extract_new_key/3, mk_random/1]). +-export([usmStatsUnsupportedSecLevels/1, + usmStatsNotInTimeWindows/1, + usmStatsUnknownUserNames/1, + usmStatsUnknownEngineIDs/1, + usmStatsWrongDigests/1, + usmStatsDecryptionErrors/1]). -export([add_user/1, add_user/13, delete_user/1]). %% Internal @@ -301,6 +309,54 @@ gc_tabs() -> %%----------------------------------------------------------------- %% Counter functions %%----------------------------------------------------------------- + +usmStatsUnsupportedSecLevels(print) -> + VarAndValue = [{usmStatsUnsupportedSecLevels, + usmStatsUnsupportedSecLevels(get)}], + snmpa_mib_lib:print_variables(VarAndValue); +usmStatsUnsupportedSecLevels(get) -> + get_counter(usmStatsUnsupportedSecLevels). + +usmStatsNotInTimeWindows(print) -> + VarAndValue = [{usmStatsNotInTimeWindows, usmStatsNotInTimeWindows(get)}], + snmpa_mib_lib:print_variables(VarAndValue); +usmStatsNotInTimeWindows(get) -> + get_counter(usmStatsNotInTimeWindows). + +usmStatsUnknownUserNames(print) -> + VarAndValue = [{usmStatsUnknownUserNames, usmStatsUnknownUserNames(get)}], + snmpa_mib_lib:print_variables(VarAndValue); +usmStatsUnknownUserNames(get) -> + get_counter(usmStatsUnknownUserNames). + +usmStatsUnknownEngineIDs(print) -> + VarAndValue = [{usmStatsUnknownEngineIDs, usmStatsUnknownEngineIDs(get)}], + snmpa_mib_lib:print_variables(VarAndValue); +usmStatsUnknownEngineIDs(get) -> + get_counter(usmStatsUnknownEngineIDs). + +usmStatsWrongDigests(print) -> + VarAndValue = [{usmStatsWrongDigests, usmStatsWrongDigests(get)}], + snmpa_mib_lib:print_variables(VarAndValue); +usmStatsWrongDigests(get) -> + get_counter(usmStatsWrongDigests). + +usmStatsDecryptionErrors(print) -> + VarAndValue = [{usmStatsDecryptionErrors, usmStatsDecryptionErrors(get)}], + snmpa_mib_lib:print_variables(VarAndValue); +usmStatsDecryptionErrors(get) -> + get_counter(usmStatsDecryptionErrors). + + +get_counter(Name) -> + case (catch ets:lookup(snmp_agent_table, Name)) of + [{_, Val}] -> + {value, Val}; + _ -> + genErr + end. + + init_vars() -> lists:map(fun maybe_create_var/1, vars()). maybe_create_var(Var) -> @@ -321,6 +377,7 @@ vars() -> usmStatsDecryptionErrors ]. + %%----------------------------------------------------------------- %% API functions %%----------------------------------------------------------------- @@ -372,6 +429,11 @@ get_user_from_security_name(EngineID, SecName) -> %%----------------------------------------------------------------- %% Instrumentation Functions %%----------------------------------------------------------------- + +usmUserSpinLock(print) -> + VarAndValue = [{usmUserSpinLock, usmUserSpinLock(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + usmUserSpinLock(new) -> snmp_generic:variable_func(new, {usmUserSpinLock, volatile}), {A1,A2,A3} = erlang:now(), diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl index 873ab00545..2cee91b081 100644 --- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl +++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. 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 @@ -18,6 +18,8 @@ %% -module(snmp_view_based_acm_mib). +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). -export([configure/1, reconfigure/1, table_next/2, get/3]). -export([vacmAccessTable/1, vacmAccessTable/3, @@ -131,7 +133,6 @@ check_vacm({vacmSecurityToGroup, SecModel, SecName, GroupName}) -> {ok, SecM} = snmp_conf:check_sec_model(SecModel, []), snmp_conf:check_string(SecName), snmp_conf:check_string(GroupName), - Vacm = {SecM, SecName, GroupName, ?'StorageType_nonVolatile', ?'RowStatus_active'}, {ok, {vacmSecurityToGroup, Vacm}}; @@ -179,15 +180,22 @@ init_tabs(Sec2Group, Access, View) -> snmpa_local_db:table_delete(db(vacmSecurityToGroupTable)), snmpa_local_db:table_create(db(vacmSecurityToGroupTable)), init_sec2group_table(Sec2Group), + + ?vdebug("create vacm access table",[]), + snmpa_vacm:cleanup(), init_access_table(Access), + ?vdebug("create vacm view-tree-family table",[]), snmpa_local_db:table_delete(db(vacmViewTreeFamilyTable)), snmpa_local_db:table_create(db(vacmViewTreeFamilyTable)), - init_view_table(View). + init_view_table(View), + + ?vdebug("table(s) initiated",[]), + ok. init_sec2group_table([Row | T]) -> -% ?vtrace("init security-to-group table: " -% "~n Row: ~p",[Row]), +%% ?vtrace("init security-to-group table: " +%% "~n Row: ~p",[Row]), Key1 = element(1, Row), Key2 = element(2, Row), Key = [Key1, length(Key2) | Key2], @@ -195,22 +203,20 @@ init_sec2group_table([Row | T]) -> init_sec2group_table(T); init_sec2group_table([]) -> true. -init_access_table([{GN, Prefix, Model, Level, Row} | T]) -> -% ?vtrace("init access table: " -% "~n GN: ~p" -% "~n Prefix: ~p" -% "~n Model: ~p" -% "~n Level: ~p" -% "~n Row: ~p",[GN, Prefix, Model, Level, Row]), - Key = [length(GN) | GN] ++ [length(Prefix) | Prefix] ++ [Model, Level], - snmpa_vacm:insert([{Key, Row}], false), - init_access_table(T); -init_access_table([]) -> - snmpa_vacm:dump_table(). +make_access_key(GN, Prefix, Model, Level) -> + [length(GN) | GN] ++ [length(Prefix) | Prefix] ++ [Model, Level]. + +make_access_entry({GN, Prefix, Model, Level, Row}) -> + Key = make_access_key(GN, Prefix, Model, Level), + {Key, Row}. + +init_access_table(TableData) -> + TableData2 = [make_access_entry(E) || E <- TableData], + snmpa_vacm:insert(TableData2, true). init_view_table([Row | T]) -> -% ?vtrace("init view table: " -% "~n Row: ~p",[Row]), +%% ?vtrace("init view table: " +%% "~n Row: ~p",[Row]), Key1 = element(1, Row), Key2 = element(2, Row), Key = [length(Key1) | Key1] ++ [length(Key2) | Key2], @@ -239,6 +245,7 @@ add_sec2group(SecModel, SecName, GroupName) -> Key = [Key1, length(Key2) | Key2], case table_cre_row(vacmSecurityToGroupTable, Key, Row) of true -> + snmpa_agent:invalidate_ca_cache(), {ok, Key}; false -> {error, create_failed} @@ -252,6 +259,7 @@ add_sec2group(SecModel, SecName, GroupName) -> delete_sec2group(Key) -> case table_del_row(vacmSecurityToGroupTable, Key) of true -> + snmpa_agent:invalidate_ca_cache(), ok; false -> {error, delete_failed} @@ -266,11 +274,9 @@ add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) -> Match, RV, WV, NV}, case (catch check_vacm(Access)) of {ok, {vacmAccess, {GN, Pref, SM, SL, Row}}} -> - Key1 = [length(GN) | GN], - Key2 = [length(Pref) | Pref], - Key3 = [SM, SL], - Key = Key1 ++ Key2 ++ Key3, + Key = make_access_key(GN, Pref, SM, SL), snmpa_vacm:insert([{Key, Row}], false), + snmpa_agent:invalidate_ca_cache(), {ok, Key}; {error, Reason} -> {error, Reason}; @@ -279,6 +285,7 @@ add_access(GroupName, Prefix, SecModel, SecLevel, Match, RV, WV, NV) -> end. delete_access(Key) -> + snmpa_agent:invalidate_ca_cache(), snmpa_vacm:delete(Key). @@ -291,6 +298,7 @@ add_view_tree_fam(ViewIndex, SubTree, Status, Mask) -> Key = [length(Key1) | Key1] ++ [length(Key2) | Key2], case table_cre_row(vacmViewTreeFamilyTable, Key, Row) of true -> + snmpa_agent:invalidate_ca_cache(), {ok, Key}; false -> {error, create_failed} @@ -304,6 +312,7 @@ add_view_tree_fam(ViewIndex, SubTree, Status, Mask) -> delete_view_tree_fam(Key) -> case table_del_row(vacmViewTreeFamilyTable, Key) of true -> + snmpa_agent:invalidate_ca_cache(), ok; false -> {error, delete_failed} @@ -346,6 +355,49 @@ vacmContextTable(Op, Arg1, Arg2) -> snmp_framework_mib:intContextTable(Op, Arg1, Arg2). +vacmSecurityToGroupTable(print) -> + Table = vacmSecurityToGroupTable, + DB = db(Table), + FOI = foi(Table), + PrintRow = + fun(Prefix, Row) -> + lists:flatten( + io_lib:format("~sSecurityModel: ~p (~w)" + "~n~sSecurityName: ~p" + "~n~sGroupName: ~p" + "~n~sStorageType: ~p (~w)" + "~n~sStatus: ~p (~w)", + [Prefix, element(?vacmSecurityModel, Row), + case element(?vacmSecurityModel, Row) of + ?SEC_ANY -> any; + ?SEC_V1 -> v1; + ?SEC_V2C -> v2c; + ?SEC_USM -> usm; + _ -> undefined + end, + Prefix, element(?vacmSecurityName, Row), + Prefix, element(?vacmGroupName, Row), + Prefix, element(?vacmSecurityToGroupStorageType, Row), + case element(?vacmSecurityToGroupStorageType, Row) of + ?'vacmSecurityToGroupStorageType_readOnly' -> readOnly; + ?'vacmSecurityToGroupStorageType_permanent' -> permanent; + ?'vacmSecurityToGroupStorageType_nonVolatile' -> nonVolatile; + ?'vacmSecurityToGroupStorageType_volatile' -> volatile; + ?'vacmSecurityToGroupStorageType_other' -> other; + _ -> undefined + end, + Prefix, element(?vacmSecurityToGroupStatus, Row), + case element(?vacmSecurityToGroupStatus, Row) of + ?'vacmSecurityToGroupStatus_destroy' -> destroy; + ?'vacmSecurityToGroupStatus_createAndWait' -> createAndWait; + ?'vacmSecurityToGroupStatus_createAndGo' -> createAndGo; + ?'vacmSecurityToGroupStatus_notReady' -> notReady; + ?'vacmSecurityToGroupStatus_notInService' -> notInService; + ?'vacmSecurityToGroupStatus_active' -> active; + _ -> undefined + end])) + end, + snmpa_mib_lib:print_table(Table, DB, FOI, PrintRow); vacmSecurityToGroupTable(Op) -> snmp_generic:table_func(Op, db(vacmSecurityToGroupTable)). @@ -400,13 +452,13 @@ verify_vacmSecurityToGroupTable_cols([{Col, Val0}|Cols], Acc) -> verify_vacmSecurityToGroupTable_col(?vacmSecurityModel, Model) -> case Model of any -> ?SEC_ANY; - v1 -> ?SEC_ANY; - v2c -> ?SEC_ANY; - usm -> ?SEC_ANY; + v1 -> ?SEC_V1; + v2c -> ?SEC_V2C; + usm -> ?SEC_USM; ?SEC_ANY -> ?SEC_ANY; - ?SEC_V1 -> ?SEC_ANY; - ?SEC_V2C -> ?SEC_ANY; - ?SEC_USM -> ?SEC_ANY; + ?SEC_V1 -> ?SEC_V1; + ?SEC_V2C -> ?SEC_V2C; + ?SEC_USM -> ?SEC_USM; _ -> ?vlog("verification of vacmSecurityModel(~w) ~p failed", [?vacmSecurityModel, Model]), @@ -443,6 +495,49 @@ verify_vacmSecurityToGroupTable_col(_, Val) -> %% {RowIndex, {Col4, Col5, ..., Col9}} %% %%----------------------------------------------------------------- +vacmAccessTable(print) -> + %% M�ste jag g�ra om alla entrien till {RowIdx, Row}? + TableInfo = get_table(vacmAccessTable), + PrintRow = + fun(Prefix, Row) -> + lists:flatten( + io_lib:format("~sContextMatch: ~p (~w)" + "~n~sReadViewName: ~p" + "~n~sWriteViewName: ~p" + "~n~sNotifyViewName: ~p" + "~n~sStorageType: ~p (~w)" + "~n~sStatus: ~p (~w)", + [Prefix, element(?vacmAccessContextMatch-3, Row), + case element(?vacmAccessContextMatch-3, Row) of + ?vacmAccessContextMatch_exact -> exact; + ?vacmAccessContextMatch_prefix -> prefix; + _ -> undefined + end, + Prefix, element(?vacmAccessReadViewName-3, Row), + Prefix, element(?vacmAccessWriteViewName-3, Row), + Prefix, element(?vacmAccessNotifyViewName-3, Row), + Prefix, element(?vacmAccessStorageType-3, Row), + case element(?vacmAccessStorageType-3, Row) of + ?vacmAccessStorageType_other -> other ; + ?vacmAccessStorageType_volatile -> volatile; + ?vacmAccessStorageType_nonVolatile -> nonVolatile; + ?vacmAccessStorageType_permanent -> permanent; + ?vacmAccessStorageType_readOnly -> readOnly; + _ -> undefined + end, + Prefix, element(?vacmAccessStatus-3, Row), + case element(?vacmAccessStatus-3, Row) of + ?vacmAccessStatus_destroy -> destroy; + ?vacmAccessStatus_createAndWait -> createAndWait; + ?vacmAccessStatus_createAndGo -> createAndGo; + ?vacmAccessStatus_notReady -> notReady; + ?vacmAccessStatus_notInService -> notInService; + ?vacmAccessStatus_active -> active; + _ -> undefined + end + ])) + end, + snmpa_mib_lib:print_table(vacmAccessTable, {ok, TableInfo}, PrintRow); vacmAccessTable(_Op) -> ok. vacmAccessTable(get, RowIndex, Cols) -> @@ -538,24 +633,24 @@ verify_vacmAccessTable_col(?vacmAccessContextPrefix, Pref) -> verify_vacmAccessTable_col(?vacmAccessSecurityModel, Model) -> case Model of any -> ?SEC_ANY; - v1 -> ?SEC_ANY; - v2c -> ?SEC_ANY; - usm -> ?SEC_ANY; + v1 -> ?SEC_V1; + v2c -> ?SEC_V2C; + usm -> ?SEC_USM; ?SEC_ANY -> ?SEC_ANY; - ?SEC_V1 -> ?SEC_ANY; - ?SEC_V2C -> ?SEC_ANY; - ?SEC_USM -> ?SEC_ANY; + ?SEC_V1 -> ?SEC_V1; + ?SEC_V2C -> ?SEC_V2C; + ?SEC_USM -> ?SEC_USM; _ -> wrongValue(?vacmAccessSecurityModel) end; verify_vacmAccessTable_col(?vacmAccessSecurityLevel, Level) -> case Level of - noAuthNoPriv -> 1; - authNoPriv -> 2; - authPriv -> 3; - 1 -> 1; - 2 -> 2; - 3 -> 3; + noAuthNoPriv -> ?vacmAccessSecurityLevel_noAuthNoPriv; + authNoPriv -> ?vacmAccessSecurityLevel_authNoPriv; + authPriv -> ?vacmAccessSecurityLevel_authPriv; + ?vacmAccessSecurityLevel_noAuthNoPriv -> ?vacmAccessSecurityLevel_noAuthNoPriv; + ?vacmAccessSecurityLevel_authNoPriv -> ?vacmAccessSecurityLevel_authNoPriv; + ?vacmAccessSecurityLevel_authPriv -> ?vacmAccessSecurityLevel_authPriv; _ -> wrongValue(?vacmAccessSecurityLevel) end; verify_vacmAccessTable_col(?vacmAccessContextMatch, Match) -> @@ -662,6 +757,7 @@ do_get_next(RowIndex, Cols) -> end end. + %%----------------------------------------------------------------- %% Functions to manipulate vacmAccessRows. %%----------------------------------------------------------------- @@ -694,29 +790,76 @@ split_cols([Col | Cols], PreCols) when Col =< 3 -> split_cols(Cols, PreCols) -> {PreCols, Cols}. +vacmViewSpinLock(print) -> + VarAndValue = [{vacmViewSpinLock, vacmViewSpinLock(get)}], + snmpa_mib_lib:print_variables(VarAndValue); + vacmViewSpinLock(new) -> - snmp_generic:variable_func(new, {vacmViewSpinLock, volatile}), + snmp_generic:variable_func(new, volatile_db(vacmViewSpinLock)), {A1,A2,A3} = erlang:now(), random:seed(A1,A2,A3), Val = random:uniform(2147483648) - 1, - snmp_generic:variable_func(set, Val, {vacmViewSpinLock, volatile}); + snmp_generic:variable_func(set, Val, volatile_db(vacmViewSpinLock)); vacmViewSpinLock(delete) -> ok; vacmViewSpinLock(get) -> - snmp_generic:variable_func(get, {vacmViewSpinLock, volatile}). + snmp_generic:variable_func(get, volatile_db(vacmViewSpinLock)). vacmViewSpinLock(is_set_ok, NewVal) -> - case snmp_generic:variable_func(get, {vacmViewSpinLock, volatile}) of + case snmp_generic:variable_func(get, volatile_db(vacmViewSpinLock)) of {value, NewVal} -> noError; _ -> inconsistentValue end; vacmViewSpinLock(set, NewVal) -> snmp_generic:variable_func(set, (NewVal + 1) rem 2147483648, - {vacmViewSpinLock, volatile}). - - + volatile_db(vacmViewSpinLock)). + + +vacmViewTreeFamilyTable(print) -> + Table = vacmViewTreeFamilyTable, + DB = db(Table), + FOI = foi(Table), + PrintRow = + fun(Prefix, Row) -> + lists:flatten( + io_lib:format("~sViewName: ~p" + "~n~sSubtree: ~p" + "~n~sMask: ~p" + "~n~sType: ~p (~w)" + "~n~sStorageType: ~p (~w)" + "~n~sStatus: ~p (~w)", + [Prefix, element(?vacmViewTreeFamilyViewName, Row), + Prefix, element(?vacmViewTreeFamilySubtree, Row), + Prefix, element(?vacmViewTreeFamilyMask, Row), + Prefix, element(?vacmViewTreeFamilyType, Row), + case element(?vacmViewTreeFamilyType, Row) of + ?vacmViewTreeFamilyType_included -> included; + ?vacmViewTreeFamilyType_excluded -> excluded; + _ -> undefined + end, + Prefix, element(?vacmViewTreeFamilyStorageType, Row), + case element(?vacmViewTreeFamilyStorageType, Row) of + ?vacmViewTreeFamilyStorageType_readOnly -> readOnly; + ?vacmViewTreeFamilyStorageType_permanent -> permanent; + ?vacmViewTreeFamilyStorageType_nonVolatile -> nonVolatile; + ?vacmViewTreeFamilyStorageType_volatile -> volatile; + ?vacmViewTreeFamilyStorageType_other -> other; + _ -> undefined + end, + Prefix, element(?vacmViewTreeFamilyStatus, Row), + case element(?vacmViewTreeFamilyStatus, Row) of + ?vacmViewTreeFamilyStatus_destroy -> destroy; + ?vacmViewTreeFamilyStatus_createAndWait -> createAndWait; + ?vacmViewTreeFamilyStatus_createAndGo -> createAndGo; + ?vacmViewTreeFamilyStatus_notReady -> notReady; + ?vacmViewTreeFamilyStatus_notInService -> notInService; + ?vacmViewTreeFamilyStatus_active -> active; + _ -> undefined + end])) + end, + snmpa_mib_lib:print_table(Table, DB, FOI, PrintRow); vacmViewTreeFamilyTable(Op) -> snmp_generic:table_func(Op, db(vacmViewTreeFamilyTable)). vacmViewTreeFamilyTable(get_next, RowIndex, Cols) -> @@ -793,7 +936,25 @@ table_next(Name, RestOid) -> snmp_generic:table_next(db(Name), RestOid). -db(X) -> snmpa_agent:db(X). +get_table(vacmAccessTable) -> + do_get_vacmAccessTable([], []). + +do_get_vacmAccessTable(Key0, Acc) -> + case snmpa_vacm:get_next_row(Key0) of + {Key, _Row} = Entry -> + do_get_vacmAccessTable(Key, [Entry | Acc]); + false -> + lists:reverse(Acc) + end. + + +%%----------------------------------------------------------------- +%% Wrappers +%%----------------------------------------------------------------- + +db(X) -> snmpa_agent:db(X). +volatile_db(X) -> {X, volatile}. + fa(vacmSecurityToGroupTable) -> ?vacmGroupName; fa(vacmViewTreeFamilyTable) -> ?vacmViewTreeFamilyMask. diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl index 5ff0883be3..c400aaddf7 100644 --- a/lib/snmp/src/agent/snmpa.erl +++ b/lib/snmp/src/agent/snmpa.erl @@ -60,6 +60,7 @@ register_subagent/3, unregister_subagent/2, + send_notification2/3, send_notification/3, send_notification/4, send_notification/5, send_notification/6, send_notification/7, send_trap/3, send_trap/4, @@ -105,9 +106,12 @@ set_request_limit/1, set_request_limit/2 ]). +-export([print_mib_info/0, print_mib_tables/0, print_mib_variables/0]). + -include("snmpa_atl.hrl"). +-include("snmpa_internal.hrl"). --define(EXTRA_INFO, undefined). +-define(DISCO_EXTRA_INFO, undefined). %%----------------------------------------------------------------- @@ -283,6 +287,186 @@ whereis_mib(Agent, Mib) when is_atom(Mib) -> %% - +mibs_info() -> + [ + {snmp_standard_mib, + [], + [ + sysDescr, + sysObjectID, + sysContact, + sysName, + sysLocation, + sysServices, + snmpEnableAuthenTraps, + sysUpTime, + snmpInPkts, + snmpOutPkts, + snmpInBadVersions, + snmpInBadCommunityNames, + snmpInBadCommunityUses, + snmpInASNParseErrs, + snmpInTooBigs, + snmpInNoSuchNames, + snmpInBadValues, + snmpInReadOnlys, + snmpInGenErrs, + snmpInTotalReqVars, + snmpInTotalSetVars, + snmpInGetRequests, + snmpInSetRequests, + snmpInGetNexts, + snmpInGetResponses, + snmpInTraps, + snmpOutTooBigs, + snmpOutNoSuchNames, + snmpOutBadValues, + snmpOutGenErrs, + snmpOutGetRequests, + snmpOutSetRequests, + snmpOutGetNexts, + snmpOutGetResponses, + snmpOutTraps + ] + }, + {snmp_framework_mib, + [ + ], + [ + snmpEngineID, + snmpEngineBoots, + snmpEngineTime, + snmpEngineMaxMessageSize + ] + }, + {snmp_view_based_acm_mib, + [ + vacmAccessTable, + vacmSecurityToGroupTable, + vacmViewTreeFamilyTable + ], + [ + vacmViewSpinLock + ] + }, + {snmp_target_mib, + [ + snmpTargetAddrTable, + snmpTargetParamsTable + ], + [ + snmpTargetSpinLock + ] + }, + {snmp_community_mib, + [ + snmpCommunityTable + ], + [] + }, + {snmp_notification_mib, + [ + snmpNotifyTable + ], + []}, + {snmp_user_based_sm_mib, + [ + usmUserTable + ], + [ + usmUserSpinLock, + usmStatsUnsupportedSecLevels, + usmStatsNotInTimeWindows, + usmStatsUnknownUserNames, + usmStatsUnknownEngineIDs, + usmStatsWrongDigests, + usmStatsDecryptionErrors + ] + } + ]. + +print_mib_info() -> + MibsInfo = mibs_info(), + print_mib_info(MibsInfo). + +print_mib_info([]) -> + io:format("~n", []), + ok; +print_mib_info([{Mod, Tables, Variables} | MibsInfo]) -> + io:format("~n** ~s ** ~n~n", [make_pretty_mib(Mod)]), + print_mib_variables2(Mod, Variables), + print_mib_tables2(Mod, Tables), + io:format("~n", []), + print_mib_info(MibsInfo). + + +print_mib_tables() -> + Tables = [{Mod, Tabs} || {Mod, Tabs, _Vars} <- mibs_info()], + print_mib_tables(Tables). + +print_mib_tables([]) -> + ok; +print_mib_tables([{Mod, Tabs}|MibTabs]) + when is_atom(Mod) andalso is_list(Tabs) -> + print_mib_tables(Mod, Tabs), + print_mib_tables(MibTabs); +print_mib_tables([_|MibTabs]) -> + print_mib_tables(MibTabs). + +print_mib_tables(_Mod, [] = _Tables) -> + ok; +print_mib_tables(Mod, Tables) -> + io:format("~n** ~s ** ~n~n", [make_pretty_mib(Mod)]), + print_mib_tables2(Mod, Tables), + io:format("~n", []). + +print_mib_tables2(Mod, Tables) -> + [(catch Mod:Table(print)) || Table <- Tables]. + + +print_mib_variables() -> + Variables = [{Mod, Vars} || {Mod, _Tabs, Vars} <- mibs_info()], + print_mib_variables(Variables). + +print_mib_variables([]) -> + ok; +print_mib_variables([{Mod, Vars}|MibVars]) + when is_atom(Mod) andalso is_list(Vars) -> + print_mib_variables(Mod, Vars), + print_mib_variables(MibVars); +print_mib_variables([_|MibVars]) -> + print_mib_variables(MibVars). + +print_mib_variables(_Mod, [] = _Vars) -> + ok; +print_mib_variables(Mod, Vars) -> + io:format("~n** ~s ** ~n~n", [make_pretty_mib(Mod)]), + print_mib_variables2(Mod, Vars), + io:format("~n", []). + +print_mib_variables2(Mod, Variables) -> + Vars = [{Var, (catch Mod:Var(get))} || Var <- Variables], + snmpa_mib_lib:print_variables(Vars). + + +make_pretty_mib(snmp_view_based_acm_mib) -> + "SNMP-VIEW-BASED-ACM-MIB"; +make_pretty_mib(snmp_target_mib) -> + "SNMP-TARGET-MIB"; +make_pretty_mib(snmp_community_mib) -> + "SNMP-COMMUNITY-MIB"; +make_pretty_mib(snmp_notification_mib) -> + "SNMP-NOTIFICATION-MIB"; +make_pretty_mib(snmp_user_based_sm_mib) -> + "SNMP-USER-BASED-SM-MIB"; +make_pretty_mib(snmp_framework_mib) -> + "SNMP-FRAMEWORK-MIB"; +make_pretty_mib(Mod) -> + atom_to_list(Mod). + + +%% - + mib_of(Oid) -> snmpa_agent:mib_of(Oid). @@ -414,22 +598,56 @@ set_request_limit(Agent, NewLimit) -> %% - +send_notification2(Agent, Notification, SendOpts) -> + snmpa_agent:send_notification(Agent, Notification, SendOpts). + send_notification(Agent, Notification, Recv) -> - send_notification(Agent, Notification, Recv, "", "", []). + SendOpts = + [ + {receiver, Recv}, + {varbinds, []}, + {name, ""}, + {context, ""}, + {extra, ?DEFAULT_NOTIF_EXTRA_INFO} + ], + send_notification2(Agent, Notification, SendOpts). send_notification(Agent, Notification, Recv, Varbinds) -> - send_notification(Agent, Notification, Recv, "", "", Varbinds). + SendOpts = + [ + {receiver, Recv}, + {varbinds, Varbinds}, + {name, ""}, + {context, ""}, + {extra, ?DEFAULT_NOTIF_EXTRA_INFO} + ], + send_notification2(Agent, Notification, SendOpts). send_notification(Agent, Notification, Recv, NotifyName, Varbinds) -> - send_notification(Agent, Notification, Recv, NotifyName, "", Varbinds). + SendOpts = + [ + {receiver, Recv}, + {varbinds, Varbinds}, + {name, NotifyName}, + {context, ""}, + {extra, ?DEFAULT_NOTIF_EXTRA_INFO} + ], + send_notification2(Agent, Notification, SendOpts). 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). + SendOpts = + [ + {receiver, Recv}, + {varbinds, Varbinds}, + {name, NotifyName}, + {context, ContextName}, + {extra, ?DEFAULT_NOTIF_EXTRA_INFO} + ], + send_notification2(Agent, Notification, SendOpts). send_notification(Agent, Notification, Recv, NotifyName, ContextName, Varbinds, LocalEngineID) @@ -437,8 +655,16 @@ send_notification(Agent, Notification, Recv, is_list(ContextName) andalso is_list(Varbinds) andalso is_list(LocalEngineID)) -> - snmpa_agent:send_trap(Agent, Notification, NotifyName, - ContextName, Recv, Varbinds, LocalEngineID). + SendOpts = + [ + {receiver, Recv}, + {varbinds, Varbinds}, + {name, NotifyName}, + {context, ContextName}, + {extra, ?DEFAULT_NOTIF_EXTRA_INFO}, + {local_engine_id, LocalEngineID} + ], + send_notification2(Agent, Notification, SendOpts). %% Kept for backwards compatibility send_trap(Agent, Trap, Community) -> @@ -473,7 +699,7 @@ discovery(TargetName, Notification, Varbinds, DiscoHandler) discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler). discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler) -> - ExtraInfo = ?EXTRA_INFO, + ExtraInfo = ?DISCO_EXTRA_INFO, discovery(TargetName, Notification, ContextName, Varbinds, DiscoHandler, ExtraInfo). diff --git a/lib/snmp/src/agent/snmpa_acm.erl b/lib/snmp/src/agent/snmpa_acm.erl index 6ad4f0b442..42a0d4d6a3 100644 --- a/lib/snmp/src/agent/snmpa_acm.erl +++ b/lib/snmp/src/agent/snmpa_acm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -62,11 +62,13 @@ %% {error, Reason} | %% {discarded, Variable, Reason} %% Types: Pdu = #pdu -%% ACMData = acm_data() = {community, Community, Address} | -%% {v3, MsgID, SecModel, SecName, SecLevel, -%% ContextEngineID, ContextName, SecData} +%% ACMData = acm_data() = +%% {community, SecModel, Community, TDomain, TAddress} | +%% {v3, MsgID, SecModel, SecName, SecLevel, +%% ContextEngineID, ContextName, SecData} %% Community = string() -%% Address = ip() ++ udp() (list) +%% TDomain = ?transportDomainUdpIpv4 | ?transportDomainUdpIpv6 +%% TAddress = ip() ++ udp() (list) %% MsgID = integer() <not used> %% SecModel = ?SEC_* (see snmp_types.hrl) %% SecName = string() @@ -114,7 +116,10 @@ error2status(_) -> genErr. %% discarded: no error response is sent %% authentication_failure: no error response is sent, a trap is generated %%----------------------------------------------------------------- -init_ca(Pdu, {community, SecModel, Community, TAddr}) -> +init_ca(Pdu, {community, SecModel, Community, TAddress}) -> + TDomain = snmp_conf:mk_tdomain(snmp_target_mib:default_domain()), + init_ca(Pdu, {community, SecModel, Community, TDomain, TAddress}); +init_ca(Pdu, {community, SecModel, Community, TDomain, TAddress}) -> %% This is a v1 or v2c request. Use SNMP-COMMUNITY-MIB to %% map the community to vacm parameters. ?vtrace("check access for ~n" @@ -126,18 +131,18 @@ init_ca(Pdu, {community, SecModel, Community, TAddr}) -> _ -> read end, ?vtrace("View type: ~p", [ViewType]), - CaCacheKey = {Community, SecModel, TAddr, ViewType}, + CaCacheKey = {Community, SecModel, TDomain, TAddress, ViewType}, case check_ca_cache(CaCacheKey) of false -> - case snmp_community_mib:community2vacm(Community, - {?snmpUDPDomain,TAddr}) of + case snmp_community_mib:community2vacm(Community, + {TDomain, TAddress}) of {SecName, _ContextEngineId, ContextName} -> %% Maybe we should check that the contextEngineID %% matches the local engineID? %% It better, since we don't impl. proxy. ?vtrace("get mib view" "~n Security name: ~p" - "~n Context name: ~p",[SecName,ContextName]), + "~n Context name: ~p",[SecName, ContextName]), case snmpa_vacm:get_mib_view(ViewType, SecModel, SecName, ?'SnmpSecurityLevel_noAuthNoPriv', ContextName) of @@ -153,7 +158,7 @@ init_ca(Pdu, {community, SecModel, Community, TAddr}) -> end; undefined -> {authentication_failure, snmpInBadCommunityNames, - {bad_community_name, TAddr, Community}} + {bad_community_name, TDomain, TAddress, Community}} end; Res -> Res @@ -219,6 +224,7 @@ upd_ca_cache(KeyVal) -> invalidate_ca_cache() -> erase(ca_cache). + %%----------------------------------------------------------------- %% Func: check(Res) -> {ok, MibView} | {discarded, Variable, Reason} %% Args: Res = {ok, AccessFunc} | diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index 00fe9be098..17cb9c9fe3 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. 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 @@ -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/7, + send_notification/3, register_notification_filter/5, unregister_notification_filter/2, which_notification_filter/1, @@ -62,14 +62,20 @@ -export([increment_counter/3]). -export([restart_worker/1, restart_set_worker/1]). +%% For backward compatibillity +-export([send_trap/6, send_trap/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/8, worker/2, worker_loop/1, do_send_trap/7]). + handle_pdu/8, worker/2, worker_loop/1, + do_send_trap/7, do_send_trap/8]). %% <BACKWARD-COMPAT> -export([handle_pdu/7]). %% </BACKWARD-COMPAT> +-include("snmpa_internal.hrl"). + -ifndef(default_verbosity). -define(default_verbosity,silence). -endif. @@ -114,14 +120,15 @@ {gb_max_vbs, GbMaxVBs}, {extra, Extra}]}). -define(mk_send_trap_wreq(TrapRec, NotifyName, ContextName, - Recv, Vbs, LocalEngineID), + Recv, Vbs, LocalEngineID, Extra), #wrequest{cmd = send_trap, info = [{trap_rec, TrapRec}, {notify_name, NotifyName}, {context_name, ContextName}, {receiver, Recv}, {varbinds, Vbs}, - {local_engine_id, LocalEngineID}]}). + {local_engine_id, LocalEngineID}, + {extra, Extra}]}). -define(mk_terminate_wreq(), #wrequest{cmd = terminate, info = []}). -define(mk_verbosity_wreq(V), #wrequest{cmd = verbosity, info = [{verbosity, V}]}). @@ -569,6 +576,11 @@ which_notification_filter(Agent) -> call(Agent, which_notification_filter). +send_notification(Agent, Notification, SendOpts) -> + Msg = {send_notif, Notification, SendOpts}, + maybe_call(Agent, Msg). + +%% <BACKWARD-COMPAT> send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds) -> ?d("send_trap -> entry with" "~n self(): ~p" @@ -580,14 +592,15 @@ send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds) -> "~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 -> - call(Agent, Msg); - true -> - Agent ! Msg - end. - + SendOpts = [ + {receiver, Recv}, + {varbinds, Varbinds}, + {name, NotifyName}, + {context, CtxName}, + {extra, ?DEFAULT_NOTIF_EXTRA_INFO} + ], + send_notification(Agent, Trap, SendOpts). + send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID) -> ?d("send_trap -> entry with" "~n self(): ~p" @@ -600,14 +613,17 @@ send_trap(Agent, Trap, NotifyName, CtxName, Recv, Varbinds, LocalEngineID) -> "~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. + SendOpts = [ + {receiver, Recv}, + {varbinds, Varbinds}, + {name, NotifyName}, + {context, CtxName}, + {extra, ?DEFAULT_NOTIF_EXTRA_INFO}, + {local_engine_id, LocalEngineID} + ], + send_notification(Agent, Trap, SendOpts). + +%% </BACKWARD-COMPAT> %% -- Discovery functions -- @@ -696,8 +712,10 @@ wis(Atom) when is_atom(Atom) -> whereis(Atom). -forward_trap(Agent, TrapRecord, NotifyName, CtxName, Recv, Varbinds) -> - Agent ! {forward_trap, TrapRecord, NotifyName, CtxName, Recv, Varbinds}. +forward_trap(Agent, TrapRecord, NotifyName, CtxName, Recv, Varbinds, + ExtraInfo) -> + Agent ! {forward_trap, TrapRecord, NotifyName, CtxName, Recv, Varbinds, + ExtraInfo}. %%----------------------------------------------------------------- @@ -788,6 +806,22 @@ handle_info(worker_available, S) -> ?vdebug("worker available",[]), {noreply, S#state{worker_state = ready}}; +handle_info({send_notif, Notification, SendOpts}, S) -> + ?vlog("[handle_info] send notif request:" + "~n Notification: ~p" + "~n SendOpts: ~p", + [Notification, SendOpts]), + case (catch handle_send_trap(S, Notification, SendOpts)) of + {ok, NewS} -> + {noreply, NewS}; + {'EXIT', R} -> + ?vinfo("Trap not sent:~n ~p", [R]), + {noreply, S}; + _ -> + {noreply, S} + end; + +%% <BACKWARD-COMPAT> handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, S) -> ?vlog("[handle_info] send trap request:" "~n Trap: ~p" @@ -796,9 +830,10 @@ handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, S) -> "~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 + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, + LocalEngineID = local_engine_id(S), + case (catch handle_send_trap(S, Trap, NotifyName, ContextName, + Recv, Varbinds, LocalEngineID, ExtraInfo)) of {ok, NewS} -> {noreply, NewS}; {'EXIT', R} -> @@ -818,8 +853,9 @@ handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds, "~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 + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, + case (catch handle_send_trap(S, Trap, NotifyName, ContextName, + Recv, Varbinds, LocalEngineID, ExtraInfo)) of {ok, NewS} -> {noreply, NewS}; {'EXIT', R} -> @@ -828,8 +864,31 @@ handle_info({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds, _ -> {noreply, S} end; +%% </BACKWARD-COMPAT> handle_info({forward_trap, TrapRecord, NotifyName, ContextName, + Recv, Varbinds, ExtraInfo}, 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]), + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + case (catch maybe_send_trap(S, TrapRecord, NotifyName, ContextName, + Recv, Varbinds, LocalEngineID, ExtraInfo)) of + {ok, NewS} -> + {noreply, NewS}; + {'EXIT', R} -> + ?vinfo("Trap not sent:~n ~p", [R]), + {noreply, S}; + _ -> + {noreply, S} + end; + +%% <BACKWARD-COMPAT> +handle_info({forward_trap, TrapRecord, NotifyName, ContextName, Recv, Varbinds}, S) -> ?vlog("[handle_info] forward trap request:" "~n TrapRecord: ~p" @@ -838,9 +897,10 @@ handle_info({forward_trap, TrapRecord, NotifyName, ContextName, "~n Recv: ~p" "~n Varbinds: ~p", [TrapRecord, NotifyName, ContextName, Recv, Varbinds]), + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, case (catch maybe_send_trap(S, TrapRecord, NotifyName, ContextName, - Recv, Varbinds, LocalEngineID)) of + Recv, Varbinds, LocalEngineID, ExtraInfo)) of {ok, NewS} -> {noreply, NewS}; {'EXIT', R} -> @@ -849,6 +909,7 @@ handle_info({forward_trap, TrapRecord, NotifyName, ContextName, _ -> {noreply, S} end; +%% </BACKWARD-COMPAT> handle_info({backup_done, Reply}, #state{backup = {_, From}} = S) -> ?vlog("[handle_info] backup done:" @@ -917,6 +978,7 @@ handle_info({'EXIT', Pid, Reason}, S) -> end, {noreply, S} end; + handle_info({'DOWN', Ref, process, Pid, {mibs_cache_reply, Reply}}, #state{mibs_cache_request = {Pid, Ref, From}} = S) -> ?vlog("reply from the mibs cache request handler (~p): ~n~p", @@ -951,6 +1013,23 @@ handle_call(restart_set_worker, _From, #state{set_worker = Pid} = S) -> end, {reply, ok, S}; +handle_call({send_notif, Notification, SendOpts}, _From, S) -> + ?vlog("[handle_call] send notif request:" + "~n Notification: ~p" + "~n SendOpts: ~p", + [Notification, SendOpts]), + case (catch handle_send_trap(S, Notification, SendOpts)) 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; + +%% <BACKWARD-COMPAT> handle_call({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, _From, S) -> ?vlog("[handle_call] send trap request:" @@ -960,19 +1039,10 @@ handle_call({send_trap, Trap, NotifyName, ContextName, Recv, Varbinds}, "~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, + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, + LocalEngineID = local_engine_id(S), case (catch handle_send_trap(S, Trap, NotifyName, ContextName, - Recv, Varbinds, LocalEngineID)) of + Recv, Varbinds, LocalEngineID, ExtraInfo)) of {ok, NewS} -> {reply, ok, NewS}; {'EXIT', Reason} -> @@ -994,8 +1064,9 @@ handle_call({send_trap, Trap, NotifyName, "~n Varbinds: ~p" "~n LocalEngineID: ~p", [Trap, NotifyName, ContextName, Recv, Varbinds, LocalEngineID]), + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, case (catch handle_send_trap(S, Trap, NotifyName, ContextName, - Recv, Varbinds, LocalEngineID)) of + Recv, Varbinds, LocalEngineID, ExtraInfo)) of {ok, NewS} -> {reply, ok, NewS}; {'EXIT', Reason} -> @@ -1005,6 +1076,7 @@ handle_call({send_trap, Trap, NotifyName, ?vinfo("Trap not sent", []), {reply, {error, send_failed}, S} end; +%% </BACKWARD-COMPAT> handle_call({discovery, TargetName, Notification, ContextName, Vbs, DiscoHandler, @@ -1256,27 +1328,27 @@ handle_call({me_of, Oid}, _From, S) -> {reply, Reply, S}; handle_call(get_log_type, _From, S) -> - ?vlog("get_log_type", []), + ?vlog("handle_call(get_log_type) -> entry with", []), Reply = handle_get_log_type(S), {reply, Reply, S}; handle_call({set_log_type, NewType}, _From, S) -> - ?vlog("set_log_type -> " + ?vlog("handle_call(set_log_type) -> entry with" "~n NewType: ~p", [NewType]), Reply = handle_set_log_type(S, NewType), {reply, Reply, S}; handle_call(get_request_limit, _From, S) -> - ?vlog("get_request_limit", []), + ?vlog("handle_call(get_request_limit) -> entry with", []), Reply = handle_get_request_limit(S), {reply, Reply, S}; handle_call({set_request_limit, NewLimit}, _From, S) -> - ?vlog("set_request_limit -> " + ?vlog("handle_call(set_request_limit) -> entry with" "~n NewLimit: ~p", [NewLimit]), Reply = handle_set_request_limit(S, NewLimit), {reply, Reply, S}; - + handle_call(stop, _From, S) -> {stop, normal, ok, S}; @@ -1580,7 +1652,10 @@ handle_backup_res([{Who, Crap}|Results], Acc) -> %% because we (for some reason) support the function %% snmpa:current_community(). %%----------------------------------------------------------------- -cheat({community, _SecModel, Community, _IpUdp}, Address, ContextName) -> +cheat({community, _SecModel, Community, _TAddress}, Address, ContextName) -> + {Community, Address, ContextName}; +cheat({community, _SecModel, Community, _TDomain, _TAddress}, + Address, ContextName) -> {Community, Address, ContextName}; cheat(_, Address, ContextName) -> {"", Address, ContextName}. @@ -1608,7 +1683,7 @@ invalidate_ca_cache() -> MasterAgent ! invalidate_ca_cache; false -> %% This is running on a sub-agent node, - %% so sent skip it + %% so skip it ok end; _ -> % Not on this node @@ -1635,19 +1710,24 @@ spawn_thread(Vsn, Pdu, PduMS, ACMData, Address, GbMaxVBs, Extra) -> proc_lib:spawn_link(?MODULE, handle_pdu, Args). spawn_trap_thread(TrapRec, NotifyName, ContextName, Recv, Vbs, - LocalEngineID) -> + LocalEngineID, ExtraInfo) -> Dict = get(), proc_lib:spawn_link(?MODULE, do_send_trap, [TrapRec, NotifyName, ContextName, - Recv, Vbs, LocalEngineID, Dict]). + Recv, Vbs, LocalEngineID, ExtraInfo, Dict]). do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, Dict) -> + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, + do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID, ExtraInfo, Dict). +do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID, ExtraInfo, 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, Vbs, - LocalEngineID, get(net_if)). + LocalEngineID, ExtraInfo, get(net_if)). worker(Master, Dict) -> lists:foreach(fun({Key, Val}) -> put(Key, Val) end, Dict), @@ -1694,12 +1774,13 @@ worker_loop(Master) -> Recv = proplists:get_value(receiver, Info), Vbs = proplists:get_value(varbinds, Info), LocalEngineID = proplists:get_value(local_engine_id, Info), + Extra = proplists:get_value(extra, Info), SendTrapRes = try begin snmpa_trap:send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, - LocalEngineID, + LocalEngineID, Extra, get(net_if)) end catch @@ -1744,11 +1825,13 @@ worker_loop(Master) -> %% We don't trap exits! {send_trap, - TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID} -> + TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, + ExtraInfo} -> ?vtrace("worker_loop -> send trap:" "~n ~p", [TrapRec]), snmpa_trap:send_trap(TrapRec, NotifyName, - ContextName, Recv, Vbs, LocalEngineID, + ContextName, Recv, Vbs, + LocalEngineID, ExtraInfo, get(net_if)), Master ! worker_available; @@ -1913,34 +1996,58 @@ handle_acm_error(Vsn, Reason, Pdu, ACMData, Address, Extra) -> ok end. +get_send_opt(Key, Default, SendOpts) -> + case lists:keysearch(Key, 1, SendOpts) of + {value, {Key, Value}} -> + Value; + false -> + Default + end. + +handle_send_trap(S, Notification, SendOpts) -> + NotifyName = get_send_opt(name, "", SendOpts), + ContextName = get_send_opt(context, "", SendOpts), + Recv = get_send_opt(receiver, no_receiver, SendOpts), + Varbinds = get_send_opt(varbinds, [], SendOpts), + ExtraInfo = get_send_opt(extra, ?DEFAULT_NOTIF_EXTRA_INFO, SendOpts), + LocalEngineID = + case lists:keysearch(local_engine_id, 1, SendOpts) of + {value, {local_engine_id, Value}} -> + Value; + false -> + local_engine_id(S) + end, + handle_send_trap(S, Notification, NotifyName, ContextName, Recv, Varbinds, + LocalEngineID, ExtraInfo). -handle_send_trap(S, TrapName, NotifyName, ContextName, Recv, Varbinds, - LocalEngineID) -> +handle_send_trap(#state{type = Type} = S, + Notification, NotifyName, ContextName, Recv, Varbinds, + LocalEngineID, ExtraInfo) -> ?vtrace("handle_send_trap -> entry with" - "~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 + "~n Agent type: ~p" + "~n TrapName: ~p" + "~n NotifyName: ~p" + "~n ContextName: ~p" + "~n LocalEngineID: ~p", + [Type, Notification, NotifyName, ContextName, LocalEngineID]), + case snmpa_trap:construct_trap(Notification, Varbinds) of {ok, TrapRecord, VarList} -> ?vtrace("handle_send_trap -> construction complete: " "~n TrapRecord: ~p" "~n VarList: ~p", [TrapRecord, VarList]), - case S#state.type of + case Type of subagent -> ?vtrace("handle_send_trap -> [sub] forward trap",[]), maybe_forward_trap(S, TrapRecord, NotifyName, - ContextName, Recv, VarList), + ContextName, Recv, VarList, ExtraInfo), {ok, S}; master_agent -> ?vtrace("handle_send_trap -> " "[master] handle send trap",[]), maybe_send_trap(S, TrapRecord, NotifyName, ContextName, Recv, VarList, - LocalEngineID) + LocalEngineID, ExtraInfo) end; error -> error @@ -1948,7 +2055,7 @@ handle_send_trap(S, TrapName, NotifyName, ContextName, Recv, Varbinds, maybe_forward_trap(#state{parent = Parent, nfilters = NFs} = S, - TrapRec, NotifyName, ContextName, Recv, V) -> + TrapRec, NotifyName, ContextName, Recv, V, ExtraInfo) -> ?vtrace("maybe_forward_trap -> entry with" "~n NFs: ~p", [NFs]), case filter_notification(NFs, [], TrapRec) of @@ -1964,13 +2071,15 @@ maybe_forward_trap(#state{parent = Parent, nfilters = NFs} = S, {send, [], TrapRec2} -> ?vtrace("maybe_forward_trap -> forward trap:" "~n ~p", [TrapRec2]), - forward_trap(Parent, TrapRec2, NotifyName, ContextName, Recv, V), + forward_trap(Parent, TrapRec2, NotifyName, ContextName, Recv, V, + ExtraInfo), {ok, S}; {send, Removed, TrapRec2} -> ?vtrace("maybe_forward_trap -> forward trap:" "~n ~p", [TrapRec2]), - forward_trap(Parent, TrapRec2, NotifyName, ContextName, Recv, V), + forward_trap(Parent, TrapRec2, NotifyName, ContextName, Recv, V, + ExtraInfo), NFs2 = del_notification_filter(Removed, NFs), {ok, S#state{nfilters = NFs2}} end. @@ -1978,7 +2087,7 @@ maybe_forward_trap(#state{parent = Parent, nfilters = NFs} = S, maybe_send_trap(#state{nfilters = NFs} = S, TrapRec, NotifyName, ContextName, Recv, Varbinds, - LocalEngineID) -> + LocalEngineID, ExtraInfo) -> ?vtrace("maybe_send_trap -> entry with" "~n NFs: ~p", [NFs]), case filter_notification(NFs, [], TrapRec) of @@ -1996,7 +2105,7 @@ maybe_send_trap(#state{nfilters = NFs} = S, "~n ~p", [TrapRec2]), do_handle_send_trap(S, TrapRec2, NotifyName, ContextName, Recv, Varbinds, - LocalEngineID); + LocalEngineID, ExtraInfo); {send, Removed, TrapRec2} -> ?vtrace("maybe_send_trap -> send trap:" @@ -2004,36 +2113,37 @@ maybe_send_trap(#state{nfilters = NFs} = S, NFs2 = del_notification_filter(Removed, NFs), do_handle_send_trap(S#state{nfilters = NFs2}, TrapRec2, NotifyName, ContextName, Recv, Varbinds, - LocalEngineID) + LocalEngineID, ExtraInfo) end. do_handle_send_trap(S, TrapRec, NotifyName, ContextName, Recv, Varbinds, - LocalEngineID) -> + LocalEngineID, ExtraInfo) -> Vbs = snmpa_trap:try_initialise_vars(get(mibserver), Varbinds), case S#state.type of subagent -> forward_trap(S#state.parent, TrapRec, NotifyName, ContextName, - Recv, Vbs), + Recv, Vbs, ExtraInfo), {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, Vbs, LocalEngineID, get(net_if)), + Recv, Vbs, LocalEngineID, ExtraInfo, + 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, Vbs, - LocalEngineID), + LocalEngineID, ExtraInfo), {ok, S}; master_agent -> %% Send to main worker ?vtrace("do_handle_send_trap -> send to main worker",[]), S#state.worker ! ?mk_send_trap_wreq(TrapRec, NotifyName, ContextName, Recv, Vbs, - LocalEngineID), + LocalEngineID, ExtraInfo), {ok, S#state{worker_state = busy}} end. @@ -2132,7 +2242,7 @@ send_discovery(S, From, TargetName, Record, ContextName, InitVars, DiscoHandler, ExtraInfo) -> case snmpa_trap:send_discovery(TargetName, Record, ContextName, - InitVars, get(net_if)) of + InitVars, get(net_if), ExtraInfo) of {ok, Sender, SecLevel} -> Disco = #disco{from = From, rec = Record, @@ -2209,9 +2319,12 @@ handle_discovery_response(#state{disco = #disco{target = TargetName, #disco{rec = Record, ctx = ContextName, ivbs = InitVars} = Disco, - case snmpa_trap:send_discovery(TargetName, Record, + case snmpa_trap:send_discovery(TargetName, + Record, ContextName, - InitVars, get(net_if)) of + InitVars, + get(net_if), + ExtraInfo) of {ok, Sender, _SecLevel} -> ?vdebug("handle_discovery_response(1) -> " "stage 2 trap sent", []), @@ -4023,6 +4136,7 @@ mapfoldl(F, Eas, Accu0, [Hd|Tail]) -> {Accu2,[R|Rs]}; mapfoldl(_F, _Eas, Accu, []) -> {Accu,[]}. + %%----------------------------------------------------------------- %% Runtime debugging of the agent. %%----------------------------------------------------------------- @@ -4089,6 +4203,18 @@ subagents_verbosity(_,_V) -> %% --------------------------------------------------------------------- +local_engine_id(#state{type = master_agent}) -> + ?DEFAULT_LOCAL_ENGINE_ID; +local_engine_id(_) -> + %% subagent - + %% we don't need this now, eventually the trap send + %% request will reach the master-agent and then it + %% will look up the proper engine id. + ignore. + + +%% --------------------------------------------------------------------- + handle_get_log_type(#state{net_if_mod = Mod}) when Mod =/= undefined -> case (catch Mod:get_log_type(get(net_if))) of @@ -4135,7 +4261,7 @@ handle_set_request_limit(_, _) -> {error, not_supported}. -agent_info(#state{worker = W, set_worker = SW}) -> +agent_info(#state{worker = W, set_worker = SW}) -> case (catch get_agent_info(W, SW)) of Info when is_list(Info) -> Info; @@ -4256,6 +4382,14 @@ user_err(F, A) -> %% --------------------------------------------------------------------- +maybe_call(Server, Req) -> + case (wis(Server) =:= self()) of + false -> + call(Server, Req); + true -> + Server ! Req + end. + call(Server, Req) -> gen_server:call(Server, Req, infinity). diff --git a/lib/snmp/src/agent/snmpa_authentication_service.erl b/lib/snmp/src/agent/snmpa_authentication_service.erl index 572fab7fbf..b5ff8460c6 100644 --- a/lib/snmp/src/agent/snmpa_authentication_service.erl +++ b/lib/snmp/src/agent/snmpa_authentication_service.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. 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 @@ -29,11 +29,12 @@ behaviour_info(_) -> %%----------------------------------------------------------------- %% init_check_access(Pdu, ACMData) %% Pdu = #pdu -%% ACMData = acm_data() = {community, Community, Address} | -%% {v3, MsgID, SecModel, SecName, SecLevel, -%% ContextEngineID, ContextName, SecData} +%% ACMData = acm_data() = {community, SecModel, Community, TDomain, TAddress} | +%% {v3, MsgID, SecModel, SecName, SecLevel, +%% ContextEngineID, ContextName, SecData} %% Community = string() -%% Address = ip() ++ udp() (list) +%% TDomain = ?transportDomainUdpIpv4 | ?transportDomainUdpIpv6 +%% TAddress = ip() ++ udp() (list) %% MsgID = integer() <not used> %% SecModel = ?SEC_* (see snmp_types.hrl) %% SecName = string() diff --git a/lib/snmp/src/agent/snmpa_conf.erl b/lib/snmp/src/agent/snmpa_conf.erl index b14a0c806c..c17a6abbd7 100644 --- a/lib/snmp/src/agent/snmpa_conf.erl +++ b/lib/snmp/src/agent/snmpa_conf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% Copyright Ericsson AB 2006-2011. 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 @@ -19,6 +19,8 @@ -module(snmpa_conf). +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). -export([ %% agent.conf agent_entry/2, @@ -46,7 +48,7 @@ %% target_addr.conf target_addr_entry/5, target_addr_entry/6, - target_addr_entry/8, target_addr_entry/10, + target_addr_entry/8, target_addr_entry/10, target_addr_entry/11, write_target_addr_config/2, write_target_addr_config/3, append_target_addr_config/2, read_target_addr_config/1, @@ -422,7 +424,8 @@ target_addr_entry(Name, EngineId, TMask) -> target_addr_entry(Name, Ip, 162, TagList, - ParamsName, EngineId, TMask, 2048). + ParamsName, EngineId, + TMask, 2048). target_addr_entry(Name, Ip, @@ -433,7 +436,8 @@ target_addr_entry(Name, TMask, MaxMessageSize) -> target_addr_entry(Name, Ip, Udp, 1500, 3, TagList, - ParamsName, EngineId, TMask, MaxMessageSize). + ParamsName, EngineId, + TMask, MaxMessageSize). target_addr_entry(Name, Ip, @@ -445,7 +449,24 @@ target_addr_entry(Name, EngineId, TMask, MaxMessageSize) -> + target_addr_entry(Name, snmp_target_mib:default_domain(), Ip, Udp, + Timeout, RetryCount, TagList, + ParamsName, EngineId, + TMask, MaxMessageSize). + +target_addr_entry(Name, + Domain, + Ip, + Udp, + Timeout, + RetryCount, + TagList, + ParamsName, + EngineId, + TMask, + MaxMessageSize) -> {Name, + Domain, Ip, Udp, Timeout, @@ -463,9 +484,13 @@ write_target_addr_config(Dir, Conf) -> "%% The data is inserted into the snmpTargetAddrTable defined\n" "%% in SNMP-TARGET-MIB, and in the snmpTargetAddrExtTable defined\n" "%% in SNMP-COMMUNITY-MIB.\n" -"%% Each row is a 10-tuple:\n" -"%% {Name, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId,\n" -"%% TMask, MaxMessageSize}.\n" +"%% Each row is a 10 or 11-tuple (Domain is optional):\n" +"%% {Name, \n" +"%% Domain, Ip, Port, \n" +"%% Timeout, RetryCount, TagList, ParamsName, EngineId,\n" +"%% TMask, MaxMessageSize}.\n" +"%% The value of Domain decide the format of the Ip and TMask values. \n" +"%% If not present, classic Ipv4 is assumed. \n" "%% The EngineId value is only used if Inform-Requests are sent to this\n" "%% target. If Informs are not sent, this value is ignored, and can be\n" "%% e.g. an empty string. However, if Informs are sent, it is essential\n" @@ -519,16 +544,31 @@ write_target_addr_conf(Fd, Hdr, Conf) -> write_target_addr_conf(Fd, Conf) -> Fun = fun(Entry) -> do_write_target_addr_conf(Fd, Entry) end, - lists:foreach(Fun, Conf). + lists:foreach(Fun, Conf), + ok. do_write_target_addr_conf(Fd, - {Name, Ip, Udp, + {Name, + Ip, Udp, + Timeout, RetryCount, TagList, + ParamsName, EngineId, + TMask, MaxMessageSize}) -> + Domain = snmp_target_mib:default_domain(), + do_write_target_addr_conf(Fd, + {Name, + Domain, Ip, Udp, + Timeout, RetryCount, TagList, + ParamsName, EngineId, + TMask, MaxMessageSize}); +do_write_target_addr_conf(Fd, + {Name, + Domain, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}) -> io:format(Fd, - "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", - [Name, Ip, Udp, Timeout, RetryCount, TagList, + "{\"~s\", ~w, ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", + [Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize]); do_write_target_addr_conf(_Fd, Crap) -> error({bad_target_addr_config, Crap}). @@ -544,13 +584,13 @@ target_params_entry(Name, Vsn) -> target_params_entry(Name, Vsn, SecName, SecLevel). target_params_entry(Name, Vsn, SecName, SecLevel) -> - MPModel = if Vsn == v1 -> v1; - Vsn == v2 -> v2c; - Vsn == v3 -> v3 + MPModel = if Vsn =:= v1 -> v1; + Vsn =:= v2 -> v2c; + Vsn =:= v3 -> v3 end, - SecModel = if Vsn == v1 -> v1; - Vsn == v2 -> v2c; - Vsn == v3 -> usm + SecModel = if Vsn =:= v1 -> v1; + Vsn =:= v2 -> v2c; + Vsn =:= v3 -> usm end, target_params_entry(Name, MPModel, SecModel, SecName, SecLevel). diff --git a/lib/snmp/src/agent/snmpa_internal.hrl b/lib/snmp/src/agent/snmpa_internal.hrl index 671a3e4aaf..c435b519d9 100644 --- a/lib/snmp/src/agent/snmpa_internal.hrl +++ b/lib/snmp/src/agent/snmpa_internal.hrl @@ -22,7 +22,9 @@ -include_lib("snmp/src/app/snmp_internal.hrl"). --define(DEFAULT_LOCAL_ENGINE_ID, snmp_framework_mib:get_engine_id()). +%% The DEFAULT_LOCAL_ENGINE_ID macro can only be used by the master_agent!! +-define(DEFAULT_LOCAL_ENGINE_ID, snmp_framework_mib:get_engine_id()). +-define(DEFAULT_NOTIF_EXTRA_INFO, {snmpa_default_notification_extra_info}). %% -- Max number of VBs in a Get-BULK response -- %% (( The default value, 1000, is *way* more )) diff --git a/lib/snmp/src/agent/snmpa_local_db.erl b/lib/snmp/src/agent/snmpa_local_db.erl index d9d6e633de..df01091d53 100644 --- a/lib/snmp/src/agent/snmpa_local_db.erl +++ b/lib/snmp/src/agent/snmpa_local_db.erl @@ -1110,7 +1110,7 @@ table_func(is_set_ok, RowIndex, Cols, NameDb) -> table_func(set, RowIndex, Cols, NameDb) -> snmp_generic:table_set_row(NameDb, nofunc, - {snmp_generic, table_try_make_consistent}, + fun snmp_generic:table_try_make_consistent/3, RowIndex, Cols); diff --git a/lib/snmp/src/agent/snmpa_mib_lib.erl b/lib/snmp/src/agent/snmpa_mib_lib.erl index ae94aca6d8..3c94cc8095 100644 --- a/lib/snmp/src/agent/snmpa_mib_lib.erl +++ b/lib/snmp/src/agent/snmpa_mib_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. 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 @@ -19,7 +19,8 @@ -module(snmpa_mib_lib). -export([table_cre_row/3, table_del_row/2]). --export([get_table/2, print_table/3, print_table/4, print_tables/1]). +-export([get_table/2]). +-export([print_variables/1, print_table/3, print_table/4, print_tables/1]). -export([gc_tab/3, gc_tab/5]). -include("SNMPv2-TC.hrl"). @@ -81,31 +82,69 @@ get_table(NameDb, FOI, Key, Acc) -> end. +print_variables(Variables) when is_list(Variables) -> + Variables2 = print_variables_prefixify(Variables), + lists:foreach(fun({Variable, ValueResult, Prefix}) -> + print_variable(Variable, ValueResult, Prefix) + end, Variables2), + ok. + +print_variable(Variable, {value, Val}, Prefix) when is_atom(Variable) -> + io:format("~w~s=> ~p~n", [Variable, Prefix, Val]); +print_variable(Variable, Error, Prefix) when is_atom(Variable) -> + io:format("~w~s=> [e] ~p~n", [Variable, Prefix, Error]). + +print_variables_prefixify(Variables) -> + MaxVarLength = print_variables_maxlength(Variables), + print_variables_prefixify(Variables, MaxVarLength, []). + +print_variables_prefixify([], _MaxVarLength, Acc) -> + lists:reverse(Acc); +print_variables_prefixify([{Var, Res}|Variables], MaxVarLength, Acc) -> + Prefix = make_variable_print_prefix(Var, MaxVarLength), + print_variables_prefixify(Variables, MaxVarLength, + [{Var, Res, Prefix}|Acc]). + +make_variable_print_prefix(Var, MaxVarLength) -> + lists:duplicate(MaxVarLength - length(atom_to_list(Var)) + 1, $ ). + +print_variables_maxlength(Variables) -> + print_variables_maxlength(Variables, 0). + +print_variables_maxlength([], MaxLength) -> + MaxLength; +print_variables_maxlength([{Var, _}|Variables], MaxLength) when is_atom(Var) -> + VarLen = length(atom_to_list(Var)), + if + VarLen > MaxLength -> + print_variables_maxlength(Variables, VarLen); + true -> + print_variables_maxlength(Variables, MaxLength) + end. + + print_tables(Tables) when is_list(Tables) -> lists:foreach(fun({Table, DB, FOI, PrintRow}) -> print_table(Table, DB, FOI, PrintRow) end, Tables), ok. -%% print_table(Table, DB, FOI, PrintRow) -> -%% TableInfo = get_table(DB(Table), FOI(Table)), -%% print_table(Table, TableInfo, PrintRow), -%% ok. - print_table(Table, DB, FOI, PrintRow) -> TableInfo = get_table(DB, FOI), print_table(Table, TableInfo, PrintRow). print_table(Table, TableInfo, PrintRow) when is_function(PrintRow, 2) -> - io:format("~w => ~n", [Table]), + io:format("~w =>", [Table]), do_print_table(TableInfo, PrintRow). +do_print_table({ok, [] = _TableInfo}, _PrintRow) -> + io:format(" -~n", []); do_print_table({ok, TableInfo}, PrintRow) when is_function(PrintRow, 2) -> + io:format("~n", []), lists:foreach(fun({RowIdx, Row}) -> io:format(" ~w => ~n~s~n", [RowIdx, PrintRow(" ", Row)]) - end, TableInfo), - io:format("~n", []); + end, TableInfo); do_print_table({error, {invalid_rowindex, BadRowIndex, []}}, _PrintRow) -> io:format("Error: Bad rowindex ~w~n", [BadRowIndex]); do_print_table({error, {invalid_rowindex, BadRowIndex, TableInfo}}, PrintRow) -> diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl index fd75b98f84..0305e1fbec 100644 --- a/lib/snmp/src/agent/snmpa_mpd.erl +++ b/lib/snmp/src/agent/snmpa_mpd.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2011. 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 @@ -32,6 +32,7 @@ -include("SNMP-MPD-MIB.hrl"). -include("SNMPv2-TM.hrl"). -include("SNMP-FRAMEWORK-MIB.hrl"). +-include("TRANSPORT-ADDRESS-MIB.hrl"). -define(VMODULE,"MPD"). -include("snmp_verbosity.hrl"). @@ -115,8 +116,8 @@ reset() -> %% Func: process_packet(Packet, TDomain, TAddress, State, Log) -> %% {ok, SnmpVsn, Pdu, PduMS, ACMData} | {discarded, Reason} %% Types: Packet = binary() -%% TDomain = snmpUDPDomain | atom() -%% TAddress = {Ip, Udp} +%% TDomain = snmpUDPDomain | transportDomain() +%% TAddress = {Ip, Udp} (*but* depends on TDomain) %% State = #state %% Purpose: This is the main Message Dispatching function. (see %% section 4.2.1 in rfc2272) @@ -182,24 +183,30 @@ discarded_pdu(Variable) -> inc(Variable). %%----------------------------------------------------------------- %% Handles a Community based message (v1 or v2c). %%----------------------------------------------------------------- -v1_v2c_proc(Vsn, NoteStore, Community, snmpUDPDomain, +v1_v2c_proc(Vsn, NoteStore, Community, Domain, {Ip, Udp}, LocalEngineID, Data, HS, Log, Packet) -> - TAddress = tuple_to_list(Ip) ++ [Udp div 256, Udp rem 256], - AgentMS = get_engine_max_message_size(LocalEngineID), - MgrMS = snmp_community_mib:get_target_addr_ext_mms(?snmpUDPDomain, - TAddress), - PduMS = case MgrMS of - {ok, MMS} when MMS < AgentMS -> MMS - HS; - _ -> AgentMS - HS - end, + TDomain = snmp_conf:mk_tdomain(Domain), + TAddress = snmp_conf:mk_taddress(Domain, Ip, Udp), + AgentMS = get_engine_max_message_size(LocalEngineID), + MgrMS = snmp_community_mib:get_target_addr_ext_mms(TDomain, TAddress), + PduMS = case MgrMS of + {ok, MMS} when MMS < AgentMS -> MMS - HS; + _ -> AgentMS - HS + end, case (catch snmp_pdus:dec_pdu(Data)) of Pdu when is_record(Pdu, pdu) -> Log(Pdu#pdu.type, Packet), inc_snmp_in_vars(Pdu), #pdu{request_id = ReqId} = Pdu, - OkRes = {ok, Vsn, Pdu, PduMS, - {community, sec_model(Vsn), Community, TAddress}}, + + %% <TDomain> + %% We have added TDomain, what are the consequences? + ACMData = + {community, sec_model(Vsn), Community, TDomain, TAddress}, + OkRes = {ok, Vsn, Pdu, PduMS, ACMData}, + %% </TDomain> + %% Make sure that we don't process duplicate SET request %% twice. We don't know what could happen in that case. %% The mgr does, so he has to generate a new SET request. @@ -216,8 +223,6 @@ v1_v2c_proc(Vsn, NoteStore, Community, snmpUDPDomain, snmp_note_store:set_note(NoteStore, 100, Key, true), %% Uses ACMData that snmpa_acm knows of. - %% snmpUDPDomain is implicit, since that's the only - %% one we handle. OkRes; true -> {discarded, duplicate_pdu} @@ -275,12 +280,12 @@ v3_proc(NoteStore, Packet, LocalEngineID, V3Hdr, Data, Log) -> "~n msgSecurityParameters = ~w", [MsgID, MMS, MsgFlags, MsgSecurityModel, SecParams]), %% 7.2.4 - SecModule = get_security_module(MsgSecurityModel), + SecModule = get_security_module(MsgSecurityModel), %% 7.2.5 - SecLevel = check_sec_level(MsgFlags), + SecLevel = check_sec_level(MsgFlags), IsReportable = snmp_misc:is_reportable(MsgFlags), %% 7.2.6 - ?vtrace("v3_proc -> [7.2.6]" + ?vtrace("v3_proc -> [7.2.4-7.2.6]" "~n SecModule = ~p" "~n SecLevel = ~p" "~n IsReportable = ~p", @@ -463,15 +468,10 @@ v3_proc(NoteStore, Packet, LocalEngineID, 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}]}, + snmpUnknownPDUHandlers_ei(SecName, SecLevel, + ContextEngineID, + ContextName), case generate_v3_report_msg(MsgID, MsgSecurityModel, Data, LocalEngineID, @@ -502,6 +502,21 @@ v3_proc(NoteStore, Packet, LocalEngineID, V3Hdr, Data, Log) -> end end. +make_error_info(Variable, Oid, SecName, Opts) -> + Val = inc(Variable), + VB = #varbind{oid = Oid, + variabletype = 'Counter32', + value = Val}, + {VB, SecName, Opts}. + +snmpUnknownPDUHandlers_ei(SecName, SecLevel, + ContextEngineID, ContextName) -> + Opts = [{securityLevel, SecLevel}, + {contextEngineID, ContextEngineID}, + {contextName, ContextName}], + make_error_info(snmpUnknownPDUHandlers, + ?snmpUnknownPDUHandlers_instance, + SecName, Opts). get_security_module(?SEC_USM) -> snmpa_usm; @@ -531,7 +546,7 @@ check_sec_module_result(Res, V3Hdr, Data, LocalEngineID, IsReportable, Log) -> ?vdebug("security module result [7.2.6-b]:" "~n Reason: ~p", [Reason]), throw({discarded, {securityError, Reason}}); - {error, Reason, ErrorInfo} when IsReportable == true -> % case 7.2.6 a + {error, Reason, ErrorInfo} when IsReportable =:= true -> % case 7.2.6 a ?vdebug("security module result when reportable [7.2.6-a]:" "~n Reason: ~p" "~n ErrorInfo: ~p", [Reason, ErrorInfo]), @@ -574,7 +589,7 @@ 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}, + {community, _SecModel, Community, _TDomain, _TAddress}, LocalEngineID, Log, _) -> case catch snmp_pdus:enc_pdu(RePdu) of @@ -977,12 +992,15 @@ generate_discovery_msg2(NoteStore, Pdu, discovery_note_timeout(Timeout) -> (Timeout div 100) + 1. -generate_discovery_msg(NoteStore, {?snmpUDPDomain, [A,B,C,D,U1,U2]}, +generate_discovery_msg(NoteStore, {TDomain, TAddress}, Pdu, ScopedPduBytes, ContextEngineID, ManagerEngineID, SecModel, SecName, SecLevelFlag, InitialUserName, ContextName, Timeout) -> + + {ok, {_Domain, Address}} = transform_taddr(TDomain, TAddress), + %% 7.1.7 ?vdebug("generate_discovery_msg -> 7.1.7 (~w)", [ManagerEngineID]), MsgID = generate_msg_id(), @@ -1023,7 +1041,7 @@ generate_discovery_msg(NoteStore, {?snmpUDPDomain, [A,B,C,D,U1,U2]}, %% Log(Packet), inc_snmp_out_vars(Pdu), ?vdebug("generate_discovery_msg -> done", []), - {Packet, {{A,B,C,D}, U1 bsl 8 + U2}}; + {Packet, Address}; Error -> throw(Error) @@ -1053,6 +1071,34 @@ generate_sec_discovery_msg(Message, SecModule, end. +transform_taddr(?snmpUDPDomain, TAddress) -> + transform_taddr(?transportDomainUdpIpv4, TAddress); +transform_taddr(?transportDomainUdpIpv4, [A, B, C, D, P1, P2]) -> + Domain = transportDomainUdpIpv4, + Addr = {A,B,C,D}, + Port = P1 bsl 8 + P2, + Address = {Addr, Port}, + {ok, {Domain, Address}}; +transform_taddr(?transportDomainUdpIpv4, BadAddr) -> + {error, {bad_transportDomainUdpIpv4_address, BadAddr}}; +transform_taddr(?transportDomainUdpIpv6, + [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]) -> + Domain = transportDomainUdpIpv6, + Addr = {A1, A2, A3, A4, A5, A6, A7, A8}, + Port = P1 bsl 8 + P2, + Address = {Addr, Port}, + {ok, {Domain, Address}}; +transform_taddr(?transportDomainUdpIpv6, BadAddr) -> + {error, {bad_transportDomainUdpIpv6_address, BadAddr}}; +transform_taddr(BadTDomain, TAddress) -> + case lists:member(BadTDomain, snmp_conf:all_tdomains()) of + true -> + {error, {unsupported_tdomain, BadTDomain, TAddress}}; + false -> + {error, {unknown_tdomain, BadTDomain, TAddress}} + end. + + process_taddrs(Dests) -> ?vtrace("process_taddrs -> entry with" "~n Dests: ~p", [Dests]), @@ -1062,46 +1108,44 @@ process_taddrs([], Acc) -> ?vtrace("process_taddrs -> entry when done with" "~n Acc: ~p", [Acc]), lists:reverse(Acc); - + %% v3 -process_taddrs([{{?snmpUDPDomain, [A,B,C,D,U1,U2]}, SecData} | T], Acc) -> +process_taddrs([{{TDomain, TAddress}, SecData} | T], Acc) -> ?vtrace("process_taddrs -> entry when v3 with" - "~n A: ~p" - "~n B: ~p" - "~n C: ~p" - "~n D: ~p" - "~n U1: ~p" - "~n U2: ~p" - "~n SecData: ~p", [A, B, C, D, U1, U2, SecData]), - Entry = {{snmpUDPDomain, {{A,B,C,D}, U1 bsl 8 + U2}}, SecData}, - process_taddrs(T, [Entry | Acc]); -%% Bad v3 -process_taddrs([{{TDomain, TAddr}, _SecData} | T], Acc) -> - ?vtrace("process_taddrs -> entry when bad v3 with" - "~n TDomain: ~p" - "~n TAddr: ~p", [TDomain, TAddr]), - user_err("Bad TDomain/TAddr: ~w/~w", [TDomain, TAddr]), - process_taddrs(T, Acc); + "~n TDomain: ~p" + "~n TAddress: ~p" + "~n SecData: ~p", [TDomain, TAddress, SecData]), + case transform_taddr(TDomain, TAddress) of + {ok, DestAddr} -> + ?vtrace("process_taddrs -> transformed: " + "~n DestAddr: ~p", [DestAddr]), + Entry = {DestAddr, SecData}, + process_taddrs(T, [Entry | Acc]); + {error, Reason} -> + ?vinfo("Failed transforming v3 domain and address" + "~n Reason: ~p", [Reason]), + user_err("Bad TDomain/TAddress: ~w/~w", [TDomain, TAddress]), + process_taddrs(T, Acc) + end; %% v1 & v2 -process_taddrs([{?snmpUDPDomain, [A,B,C,D,U1,U2]} | T], Acc) -> +process_taddrs([{TDomain, TAddress} | T], Acc) -> ?vtrace("process_taddrs -> entry when v1/v2 with" - "~n A: ~p" - "~n B: ~p" - "~n C: ~p" - "~n D: ~p" - "~n U1: ~p" - "~n U2: ~p", [A, B, C, D, U1, U2]), - Entry = {snmpUDPDomain, {{A,B,C,D}, U1 bsl 8 + U2}}, - process_taddrs(T, [Entry | Acc]); -%% Bad v1 or v2 -process_taddrs([{TDomain, TAddr} | T], Acc) -> - ?vtrace("process_taddrs -> entry when bad v1/v2 with" - "~n TDomain: ~p" - "~n TAddr: ~p", [TDomain, TAddr]), - user_err("Bad TDomain/TAddr: ~w/~w", [TDomain, TAddr]), - process_taddrs(T, Acc); + "~n TDomain: ~p" + "~n TAddress: ~p", [TDomain, TAddress]), + case transform_taddr(TDomain, TAddress) of + {ok, DestAddr} -> + ?vtrace("process_taddrs -> transformed: " + "~n DestAddr: ~p", [DestAddr]), + Entry = DestAddr, + process_taddrs(T, [Entry | Acc]); + {error, Reason} -> + ?vinfo("Failed transforming v1/v2 domain and address: " + "~n Reason: ~p", [Reason]), + user_err("Bad TDomain/TAddress: ~w/~w", [TDomain, TAddress]), + process_taddrs(T, Acc) + end; process_taddrs(Crap, Acc) -> - throw({error, {taddrs_crap, Crap, Acc}}). + throw({error, {bad_taddrs, Crap, Acc}}). mk_v1_v2_packet_list(To, Packet, Len, Pdu) -> diff --git a/lib/snmp/src/agent/snmpa_net_if.erl b/lib/snmp/src/agent/snmpa_net_if.erl index 97a7a63dee..79c85a6e4e 100644 --- a/lib/snmp/src/agent/snmpa_net_if.erl +++ b/lib/snmp/src/agent/snmpa_net_if.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2011. 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 @@ -314,6 +314,14 @@ loop(S) -> NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, undefined), loop(NewS); + %% We dont use the extra-info at this time, ... + {send_pdu, Vsn, Pdu, MsgData, To, _ExtraInfo} -> + ?vdebug("send pdu: " + "~n Pdu: ~p" + "~n To: ~p", [Pdu, To]), + NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, undefined), + loop(NewS); + %% Informs {send_pdu_req, Vsn, Pdu, MsgData, To, From} -> ?vdebug("send pdu request: " @@ -324,7 +332,18 @@ loop(S) -> NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, From), loop(NewS); + %% We dont use the extra-info at this time, ... + {send_pdu_req, Vsn, Pdu, MsgData, To, From, _ExtraInfo} -> + ?vdebug("send pdu request: " + "~n Pdu: ~p" + "~n To: ~p" + "~n From: ~p", + [Pdu, To, toname(From)]), + NewS = maybe_handle_send_pdu(S, Vsn, Pdu, MsgData, To, From), + loop(NewS); + %% Discovery Inform + %% <BACKWARD-COMPAT> {send_discovery, Pdu, MsgData, To, From} -> ?vdebug("received send discovery request: " "~n Pdu: ~p" @@ -333,6 +352,18 @@ loop(S) -> [Pdu, To, toname(From)]), NewS = handle_send_discovery(S, Pdu, MsgData, To, From), loop(NewS); + %% </BACKWARD-COMPAT> + + %% Discovery Inform + {send_discovery, Pdu, MsgData, To, From, ExtraInfo} -> + ?vdebug("received send discovery request: " + "~n Pdu: ~p" + "~n To: ~p" + "~n From: ~p" + "~n ExtraInfo: ~p", + [Pdu, To, toname(From), ExtraInfo]), + NewS = handle_send_discovery(S, Pdu, MsgData, To, From), + loop(NewS); {discarded_pdu, _Vsn, ReqId, _ACMData, Variable, _Extra} -> ?vdebug("discard PDU: ~p", [Variable]), @@ -504,7 +535,6 @@ handle_discovery_response(_Ip, _Port, #pdu{request_id = ReqId} = Pdu, S end. - handle_recv(#state{usock = Sock, mpd_state = MpdState, note_store = NS, @@ -513,7 +543,9 @@ handle_recv(#state{usock = Sock, LogF = fun(Type, Data) -> log(Log, Type, Data, Ip, Port) end, - case (catch snmpa_mpd:process_packet(Packet, snmpUDPDomain, {Ip, Port}, + Domain = snmp_conf:which_domain(Ip), % What the ****... + case (catch snmpa_mpd:process_packet(Packet, + Domain, {Ip, Port}, MpdState, NS, LogF)) of {ok, _Vsn, Pdu, _PduMS, {discovery, ManagerEngineId}} -> handle_discovery_response(Ip, Port, Pdu, ManagerEngineId, S); @@ -636,7 +668,6 @@ process_taddrs([{{_Domain, AddrAndPort}, _SecData}|T], Acc) -> process_taddrs([{_Domain, AddrAndPort}|T], Acc) -> process_taddrs(T, [AddrAndPort|Acc]). - merge_taddrs(To1, To2) -> merge_taddrs(To1, To2, []). @@ -776,15 +807,49 @@ handle_send_pdu1(#state{log = Log, usock = Sock, filter = FilterMod}, Type, Addresses) -> SendFun = - fun({snmpUDPDomain, {Ip, Port}, Packet}) when is_binary(Packet) -> - ?vdebug("sending packet:" + fun({snmpUDPDomain, {Ip, Port}, Packet}) + when is_binary(Packet) -> + ?vdebug("[snmpUDPDomain] sending packet:" + "~n size: ~p" + "~n to: ~p:~p", + [sz(Packet), Ip, Port]), + maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); + + ({snmpUDPDomain, {Ip, Port}, {Packet, _LogData}}) + when is_binary(Packet) -> + ?vdebug("[snmpUDPDomain] sending encrypted packet:" + "~n size: ~p" + "~n to: ~p:~p", + [sz(Packet), Ip, Port]), + maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); + + ({transportDomainUdpIpv4, {Ip, Port}, Packet}) + when is_binary(Packet) -> + ?vdebug("[transportDomainUdpIpv4] sending packet:" + "~n size: ~p" + "~n to: ~p:~p", + [sz(Packet), Ip, Port]), + maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); + + ({transportDomainUdpIpv4, {Ip, Port}, {Packet, _LogData}}) + when is_binary(Packet) -> + ?vdebug("[transportDomainUdpIpv4] sending encrypted packet:" + "~n size: ~p" + "~n to: ~p:~p", + [sz(Packet), Ip, Port]), + maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); + + ({transportDomainUdpIpv6, {Ip, Port}, Packet}) + when is_binary(Packet) -> + ?vdebug("[transportDomainUdpIpv6] sending packet:" "~n size: ~p" "~n to: ~p:~p", [sz(Packet), Ip, Port]), maybe_udp_send(FilterMod, Log, Type, Sock, Ip, Port, Packet); - ({snmpUDPDomain, {Ip, Port}, {Packet, _LogData}}) when is_binary(Packet) -> - ?vdebug("sending encrypted packet:" + ({transportDomainUdpIpv6, {Ip, Port}, {Packet, _LogData}}) + when is_binary(Packet) -> + ?vdebug("[transportDomainUdpIpv6] sending encrypted packet:" "~n size: ~p" "~n to: ~p:~p", [sz(Packet), Ip, Port]), diff --git a/lib/snmp/src/agent/snmpa_set_lib.erl b/lib/snmp/src/agent/snmpa_set_lib.erl index 191029f6db..9f355855b4 100644 --- a/lib/snmp/src/agent/snmpa_set_lib.erl +++ b/lib/snmp/src/agent/snmpa_set_lib.erl @@ -143,8 +143,8 @@ consistency_check(Varbinds) -> consistency_check(Varbinds, []). consistency_check([{TableOid, TableVbs} | Varbinds], Done) -> ?vtrace("consistency_check -> entry with" - "~n TableOid: ~p" - "~n TableVbs: ~p",[TableOid,TableVbs]), + "~n TableOid: ~p" + "~n TableVbs: ~p", [TableOid, TableVbs]), TableOpsWithShortOids = deletePrefixes(TableOid, TableVbs), [#ivarbind{mibentry = MibEntry}|_] = TableVbs, case is_set_ok_table(MibEntry, TableOpsWithShortOids) of @@ -158,7 +158,7 @@ consistency_check([{TableOid, TableVbs} | Varbinds], Done) -> end; consistency_check([IVarbind | Varbinds], Done) -> ?vtrace("consistency_check -> entry with" - "~n IVarbind: ~p",[IVarbind]), + "~n IVarbind: ~p", [IVarbind]), #ivarbind{varbind = Varbind, mibentry = MibEntry} = IVarbind, #varbind{value = Value, org_index = OrgIndex} = Varbind, case is_set_ok_variable(MibEntry, Value) of @@ -358,32 +358,39 @@ make_value_a_correct_value(Value, ASN1Type, Mfa) -> %% Runtime debug support %%----------------------------------------------------------------- -% XXX: This function match on the exakt return codes from EXIT -% messages. As of this writing it was not decided if this is -% the right way so don't blindly do things this way. -% -% We fake a real EXIT signal as the return value because the -% result is passed to the function snmpa_agent:validate_err() -% that expect it. +%% XYZ: This function match on the exakt return codes from EXIT +%% messages. As of this writing it was not decided if this is +%% the right way so don't blindly do things this way. +%% +%% We fake a real EXIT signal as the return value because the +%% result is passed to the function snmpa_agent:validate_err() +%% that expect it. dbg_apply(M,F,A) -> - Result = - case get(verbosity) of - false -> - (catch apply(M,F,A)); - _ -> - ?vlog("~n apply: ~w,~w,~p~n", [M,F,A]), - Res = (catch apply(M,F,A)), - ?vlog("~n returned: ~p", [Res]), - Res - end, - case Result of + case maybe_verbose_apply(M, F, A) of + %% <Future proofing> + %% As of R15 we get extra info containing, + %% among other things, line numbers. + {'EXIT', {undef, [{M, F, A, _} | _]}} -> + {'EXIT', {hook_undef, {M, F, A}}}; + {'EXIT', {function_clause, [{M, F, A, _} | _]}} -> + {'EXIT', {hook_function_clause, {M, F, A}}}; + + %% This is really overkill, but just to be on the safe side... + {'EXIT', {undef, {M, F, A, _}}} -> + {'EXIT', {hook_undef, {M, F, A}}}; + {'EXIT', {function_clause, {M, F, A, _}}} -> + {'EXIT', {hook_function_clause, {M, F, A}}}; + %% </Future proofing> + + + %% Old format format for compatibility {'EXIT', {undef, [{M, F, A} | _]}} -> {'EXIT', {hook_undef, {M, F, A}}}; {'EXIT', {function_clause, [{M, F, A} | _]}} -> {'EXIT', {hook_function_clause, {M, F, A}}}; - % XXX: Old format for compatibility + % XYZ: Older format for compatibility {'EXIT', {undef, {M, F, A}}} -> {'EXIT', {hook_undef, {M, F, A}}}; {'EXIT', {function_clause, {M, F, A}}} -> @@ -393,3 +400,15 @@ dbg_apply(M,F,A) -> Result end. + +maybe_verbose_apply(M, F, A) -> + case get(verbosity) of + false -> + (catch apply(M,F,A)); + _ -> + ?vlog("~n apply: ~w,~w,~p~n", [M,F,A]), + Res = (catch apply(M,F,A)), + ?vlog("~n returned: ~p", [Res]), + Res + end. + diff --git a/lib/snmp/src/agent/snmpa_target_cache.erl b/lib/snmp/src/agent/snmpa_target_cache.erl index 6fdecacc68..2aa35aa46a 100644 --- a/lib/snmp/src/agent/snmpa_target_cache.erl +++ b/lib/snmp/src/agent/snmpa_target_cache.erl @@ -1,7 +1,7 @@ %% %% %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 @@ -21,6 +21,8 @@ -behaviour(gen_server). %% External exports +%% Avoid warning for local function demonitor/1 clashing with autoimported BIF. +-compile({no_auto_import,[demonitor/1]}). -export([start_link/2, stop/0, verbosity/1]). -export([ diff --git a/lib/snmp/src/agent/snmpa_trap.erl b/lib/snmp/src/agent/snmpa_trap.erl index 3b31c8d909..994d926224 100644 --- a/lib/snmp/src/agent/snmpa_trap.erl +++ b/lib/snmp/src/agent/snmpa_trap.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2010. All Rights Reserved. +%% Copyright Ericsson AB 1996-2011. 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 @@ -24,27 +24,34 @@ %% External exports -export([construct_trap/2, try_initialise_vars/2, - send_trap/6, send_trap/7]). --export([send_discovery/5]). + send_trap/6, send_trap/7, send_trap/8]). +-export([send_discovery/6]). %% Internal exports --export([init_v2_inform/9, - init_v3_inform/9, init_v3_inform/10, +-export([init_v2_inform/9, init_v2_inform/10, + init_v3_inform/9, init_v3_inform/10, init_v3_inform/11, 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"). --include("SNMP-FRAMEWORK-MIB.hrl"). --include("SNMP-TARGET-MIB.hrl"). +-export([init_discovery_inform/13, send_discovery_inform/5]). + +%% <BACKWARD-COMPAT> +-export([send_discovery/5, + init_discovery_inform/12]). +%% </BACKWARD-COMPAT> + +-include_lib("snmp/include/snmp_types.hrl"). +-include_lib("snmp/src/agent/snmpa_internal.hrl"). +-include_lib("snmp/include/SNMPv2-MIB.hrl"). +-include_lib("snmp/include/SNMPv2-TM.hrl"). +-include_lib("snmp/include/SNMPv2-TC.hrl"). +-include_lib("snmp/include/SNMP-FRAMEWORK-MIB.hrl"). +-include_lib("snmp/include/SNMP-TARGET-MIB.hrl"). +-include_lib("snmp/include/TRANSPORT-ADDRESS-MIB.hrl"). -define(enterpriseSpecific, 6). -define(VMODULE,"TRAP"). -include("snmp_verbosity.hrl"). +-include("snmpa_internal.hrl"). %%----------------------------------------------------------------- @@ -335,41 +342,51 @@ make_varbind_list(Varbinds) -> %% SnmpTargetAddrTable (using the Tag). %%----------------------------------------------------------------- send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, NetIf) -> + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, + LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, + send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, + LocalEngineID, ExtraInfo, NetIf). + +send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, ExtraInfo, NetIf) -> LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, - LocalEngineID, NetIf). + LocalEngineID, ExtraInfo, NetIf). %% The agent normally does not care about the result, %% but since it can be usefull when debugging, add %% some info when we fail to send the trap(s). -send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, NetIf) -> +send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, LocalEngineID, + ExtraInfo, NetIf) -> try begin do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, - LocalEngineID, NetIf) + LocalEngineID, ExtraInfo, NetIf) end catch T:E -> Info = [{args, [TrapRec, NotifyName, ContextName, - Recv, Vbs, LocalEngineID, NetIf]}, + Recv, Vbs, LocalEngineID, ExtraInfo, NetIf]}, {tag, T}, {err, E}, {stacktrace, erlang:get_stacktrace()}], {error, {failed_sending_trap, Info}} end. - do_send_trap(TrapRec, NotifyName, ContextName, Recv, Vbs, - LocalEngineID, NetIf) -> + LocalEngineID, ExtraInfo, NetIf) -> VarbindList = make_varbind_list(Vbs), Dests = find_dests(NotifyName), send_trap_pdus(Dests, ContextName, {TrapRec, VarbindList}, [], [], [], - Recv, LocalEngineID, NetIf). + Recv, LocalEngineID, ExtraInfo, NetIf). send_discovery(TargetName, Record, ContextName, Vbs, NetIf) -> + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, + send_discovery(TargetName, Record, ContextName, Vbs, NetIf, ExtraInfo). +send_discovery(TargetName, Record, ContextName, Vbs, NetIf, ExtraInfo) -> case find_dest(TargetName) of {ok, Dest} -> - send_discovery_pdu(Dest, Record, ContextName, Vbs, NetIf); + send_discovery_pdu(Dest, Record, ContextName, Vbs, NetIf, + ExtraInfo); Error -> Error end. @@ -377,8 +394,13 @@ send_discovery(TargetName, Record, ContextName, Vbs, NetIf) -> get_values(VariablesWithType) -> {Order, Varbinds} = extract_order(VariablesWithType, 1), + ?vtrace("get_values -> " + "~n Order: ~p" + "~n Varbinds: ~p", [Order, Varbinds]), case snmpa_agent:do_get(snmpa_acm:get_root_mib_view(), Varbinds, true) of {noError, _, NewVarbinds} -> + ?vtrace("get_values -> values retrieved" + "~n NewVarbinds: ~p", [NewVarbinds]), %% NewVarbinds is the result of: %% first a reverse, then a sort on the oid field and finally %% a reverse during the get-processing so we need to re-sort @@ -456,11 +478,13 @@ split_variables([]) -> {[], []}. %% NOTE: This function is executed in the master agent's context %%----------------------------------------------------------------- find_dests("") -> + ?vtrace("find destinations", []), snmp_notification_mib:get_targets(); find_dests(NotifyName) -> + ?vtrace("find destinations for ~p", [NotifyName]), case snmp_notification_mib:get_targets(NotifyName) of [] -> - ?vlog("No dests found for snmpNotifyName: ~p",[NotifyName]), + ?vlog("No dests found for NotifyName: ~p", [NotifyName]), []; Dests -> Dests @@ -545,7 +569,8 @@ find_dest(TargetName) -> send_discovery_pdu({Dest, TargetName, {SecModel, SecName, SecLevel}, Timeout, Retry}, - Record, ContextName, Vbs, NetIf) -> + Record, ContextName, Vbs, NetIf, + ExtraInfo) -> ?vdebug("send_discovery_pdu -> entry with " "~n Destination address: ~p" "~n Target name: ~p" @@ -555,9 +580,10 @@ send_discovery_pdu({Dest, TargetName, {SecModel, SecName, SecLevel}, "~n Timeout: ~p" "~n Retry: ~p" "~n Record: ~p" - "~n ContextName: ~p", + "~n ContextName: ~p" + "~n ExtraInfo: ~p", [Dest, TargetName, SecModel, SecName, SecLevel, - Timeout, Retry, Record, ContextName]), + Timeout, Retry, Record, ContextName, ExtraInfo]), case get_mib_view(SecModel, SecName, SecLevel, ContextName) of {ok, MibView} -> case check_all_varbinds(Record, Vbs, MibView) of @@ -567,7 +593,7 @@ send_discovery_pdu({Dest, TargetName, {SecModel, SecName, SecLevel}, SecModel, SecName, SecLevel, TargetName, ContextName, Timeout, Retry, - SysUpTime, NetIf); + SysUpTime, NetIf, ExtraInfo); false -> {error, {mibview_validation_failed, Vbs, MibView}} end; @@ -577,7 +603,7 @@ send_discovery_pdu({Dest, TargetName, {SecModel, SecName, SecLevel}, send_discovery_pdu(Record, Dest, Vbs, SecModel, SecName, SecLevel, TargetName, - ContextName, Timeout, Retry, SysUpTime, NetIf) -> + ContextName, Timeout, Retry, SysUpTime, NetIf, ExtraInfo) -> {_Oid, IVbs} = mk_v2_trap(Record, Vbs, SysUpTime), % v2 refers to SMIv2; Sender = proc_lib:spawn_link(?MODULE, init_discovery_inform, [self(), @@ -586,13 +612,25 @@ send_discovery_pdu(Record, Dest, Vbs, ContextName, Timeout, Retry, IVbs, NetIf, - get(verbosity)]), + get(verbosity), + ExtraInfo]), {ok, Sender, SecLevel}. init_discovery_inform(Parent, Dest, SecModel, SecName, SecLevel, TargetName, ContextName, Timeout, Retry, Vbs, NetIf, Verbosity) -> + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, + init_discovery_inform(Parent, + Dest, + SecModel, SecName, SecLevel, TargetName, + ContextName, Timeout, Retry, Vbs, NetIf, + Verbosity, ExtraInfo). +init_discovery_inform(Parent, + Dest, + SecModel, SecName, SecLevel, TargetName, + ContextName, Timeout, Retry, Vbs, NetIf, + Verbosity, ExtraInfo) -> put(verbosity, Verbosity), put(sname, madis), Pdu = make_discovery_pdu(Vbs), @@ -600,7 +638,7 @@ init_discovery_inform(Parent, SecLevelFlag = mk_flag(SecLevel), SecData = {SecModel, SecName, SecLevelFlag, TargetName}, MsgData = {SecData, ContextEngineId, ContextName}, - Msg = {send_discovery, Pdu, MsgData, Dest, self()}, + Msg = {send_discovery, Pdu, MsgData, Dest, self(), ExtraInfo}, ?MODULE:send_discovery_inform(Parent, Timeout*10, Retry, Msg, NetIf). %% note_timeout(Timeout, Retry) @@ -644,11 +682,11 @@ send_discovery_inform(Parent, Timeout, Retry, Msg, NetIf) -> %% 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], +send_trap_pdus([{DestAddr, TargetName, + {MpModel, SecModel, SecName, SecLevel}, Type} | T], ContextName, {TrapRec, Vbs}, V1Res, V2Res, V3Res, Recv, - LocalEngineID, NetIf) -> + LocalEngineID, ExtraInfo, NetIf) -> ?vdebug("send trap pdus: " "~n Destination address: ~p" "~n Target name: ~p" @@ -674,13 +712,13 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel}, send_trap_pdus(T, ContextName, {TrapRec, Vbs}, [{DestAddr, Community} | V1Res], V2Res, V3Res, Recv, - LocalEngineID, NetIf); + LocalEngineID, ExtraInfo, NetIf); undefined -> ?vdebug("No community found for v1 dest: ~p", [element(2, DestAddr)]), send_trap_pdus(T, ContextName, {TrapRec, Vbs}, V1Res, V2Res, V3Res, Recv, - LocalEngineID, NetIf) + LocalEngineID, ExtraInfo, NetIf) end; true when MpModel =:= ?MP_V2C -> ?vtrace("send_trap_pdus -> v2c mp model",[]), @@ -695,13 +733,14 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel}, send_trap_pdus(T, ContextName, {TrapRec, Vbs}, V1Res, [{DestAddr, Community, Type}|V2Res], - V3Res, Recv, LocalEngineID, NetIf); + V3Res, Recv, + LocalEngineID, ExtraInfo, NetIf); undefined -> ?vdebug("No community found for v2c dest: ~p", [element(2, DestAddr)]), send_trap_pdus(T, ContextName, {TrapRec, Vbs}, V1Res, V2Res, V3Res, Recv, - LocalEngineID, NetIf) + LocalEngineID, ExtraInfo, NetIf) end; true when MpModel =:= ?MP_V3 -> ?vtrace("send_trap_pdus -> v3 mp model",[]), @@ -710,20 +749,20 @@ send_trap_pdus([{DestAddr, TargetName, {MpModel, SecModel, SecName, SecLevel}, send_trap_pdus(T, ContextName, {TrapRec, Vbs}, V1Res, V2Res, [{DestAddr, MsgData, Type} | V3Res], - Recv, LocalEngineID, NetIf); + Recv, LocalEngineID, ExtraInfo, NetIf); true -> ?vlog("bad MpModel ~p for dest ~p", [MpModel, element(2, DestAddr)]), send_trap_pdus(T, ContextName, {TrapRec, Vbs}, V1Res, V2Res, V3Res, Recv, - LocalEngineID, NetIf); + LocalEngineID, ExtraInfo, 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, - LocalEngineID, NetIf) + LocalEngineID, ExtraInfo, NetIf) end; {discarded, Reason} -> ?vlog("mib view error ~p for" @@ -731,24 +770,27 @@ 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, LocalEngineID, NetIf) + V1Res, V2Res, V3Res, Recv, + LocalEngineID, ExtraInfo, NetIf) end; -send_trap_pdus([], ContextName, {TrapRec, Vbs}, V1Res, V2Res, V3Res, - Recv, LocalEngineID, NetIf) -> +send_trap_pdus([], ContextName, {TrapRec, Vbs}, + V1Res, V2Res, V3Res, Recv, + LocalEngineID, ExtraInfo, + NetIf) -> SysUpTime = snmp_standard_mib:sys_up_time(), ?vdebug("send trap pdus with sysUpTime ~p", [SysUpTime]), InformRecvs = get_inform_recvs(V2Res ++ V3Res), InformTargets = [Addr || {Addr, _, _, _} <- InformRecvs], 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, LocalEngineID, NetIf, + send_v1_trap(TrapRec, V1Res, Vbs, ExtraInfo, NetIf, SysUpTime), + send_v2_trap(TrapRec, V2Res, Vbs, Recv, ExtraInfo, NetIf, SysUpTime), + send_v3_trap(TrapRec, V3Res, Vbs, Recv, LocalEngineID, ExtraInfo, NetIf, SysUpTime, ContextName). -send_v1_trap(_TrapRec, [], _Vbs, _NetIf, _SysUpTime) -> +send_v1_trap(_TrapRec, [], _Vbs, _ExtraInfo, _NetIf, _SysUpTime) -> ok; send_v1_trap(#trap{enterpriseoid = Enter, specificcode = Spec}, - V1Res, Vbs, NetIf, SysUpTime) -> + V1Res, Vbs, ExtraInfo, NetIf, SysUpTime) -> ?vdebug("prepare to send v1 trap " "~n '~p'" "~n with" @@ -760,9 +802,10 @@ send_v1_trap(#trap{enterpriseoid = Enter, specificcode = Spec}, lists:foreach(fun({Community, Addrs}) -> ?vtrace("send v1 trap pdu to ~p",[Addrs]), NetIf ! {send_pdu, 'version-1', TrapPdu, - {community, Community}, Addrs} + {community, Community}, Addrs, ExtraInfo} end, AddrCommunities); -send_v1_trap(#notification{oid = Oid}, V1Res, Vbs, NetIf, SysUpTime) -> +send_v1_trap(#notification{oid = Oid}, V1Res, Vbs, ExtraInfo, 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]), @@ -784,31 +827,31 @@ send_v1_trap(#notification{oid = Oid}, V1Res, Vbs, NetIf, SysUpTime) -> lists:foreach(fun({Community, Addrs}) -> ?vtrace("send v1 trap to ~p",[Addrs]), NetIf ! {send_pdu, 'version-1', TrapPdu, - {community, Community}, Addrs} + {community, Community}, Addrs, ExtraInfo} end, AddrCommunities). -send_v2_trap(_TrapRec, [], _Vbs, _Recv, _NetIf, _SysUpTime) -> +send_v2_trap(_TrapRec, [], _Vbs, _Recv, _ExtraInfo, _NetIf, _SysUpTime) -> ok; -send_v2_trap(TrapRec, V2Res, Vbs, Recv, NetIf, SysUpTime) -> +send_v2_trap(TrapRec, V2Res, Vbs, Recv, ExtraInfo, 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). + TrapRecvs = get_trap_recvs(V2Res), + InformRecvs = get_inform_recvs(V2Res), + do_send_v2_trap(TrapRecvs, IVbs, ExtraInfo, NetIf), + do_send_v2_inform(InformRecvs, IVbs, Recv, ExtraInfo, NetIf). -send_v3_trap(_TrapRec, [], _Vbs, _Recv, _LocalEngineID, +send_v3_trap(_TrapRec, [], _Vbs, _Recv, _LocalEngineID, _ExtraInfo, _NetIf, _SysUpTime, _ContextName) -> ok; -send_v3_trap(TrapRec, V3Res, Vbs, Recv, LocalEngineID, +send_v3_trap(TrapRec, V3Res, Vbs, Recv, LocalEngineID, ExtraInfo, 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_trap(TrapRecvs, ContextName, IVbs, ExtraInfo, NetIf), do_send_v3_inform(InformRecvs, ContextName, IVbs, Recv, - LocalEngineID, NetIf). + LocalEngineID, ExtraInfo, NetIf). mk_v2_trap(#notification{oid = Oid}, Vbs, SysUpTime) -> @@ -846,60 +889,70 @@ get_inform_recvs(InformRecvs) -> [{Addr, MsgData, Timeout, Retry} || {Addr, MsgData, {inform, Timeout, Retry}} <- InformRecvs]. -do_send_v2_trap([], _Vbs, _NetIf) -> +do_send_v2_trap([], _Vbs, _ExtraInfo, _NetIf) -> ok; -do_send_v2_trap(Recvs, Vbs, NetIf) -> +do_send_v2_trap(Recvs, Vbs, ExtraInfo, 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} + {community, Community}, Addrs, ExtraInfo} end, AddrCommunities), ok. -do_send_v2_inform([], _Vbs, _Recv, _NetIf) -> +do_send_v2_inform([], _Vbs, _Recv, _ExtraInfo, _NetIf) -> ok; -do_send_v2_inform(Recvs, Vbs, Recv, NetIf) -> +do_send_v2_inform(Recvs, Vbs, Recv, ExtraInfo, NetIf) -> 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, + Recv, ExtraInfo, NetIf, Community, get(verbosity), get(sname)]) end, Recvs). -do_send_v3_trap([], _ContextName, _Vbs, _NetIf) -> +do_send_v3_trap([], _ContextName, _Vbs, _ExtraInfo, _NetIf) -> ok; -do_send_v3_trap(Recvs, ContextName, Vbs, NetIf) -> +do_send_v3_trap(Recvs, ContextName, Vbs, ExtraInfo, 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]} + {v3, ContextEngineId, ContextName}, + [Recv], ExtraInfo} end, Recvs), ok. -do_send_v3_inform([], _ContextName, _Vbs, _Recv, _LocalEngineID, _NetIf) -> +do_send_v3_inform([], _ContextName, _Vbs, _Recv, + _LocalEngineID, _ExtraInfo, _NetIf) -> ok; -do_send_v3_inform(Recvs, ContextName, Vbs, Recv, LocalEngineID, NetIf) -> +do_send_v3_inform(Recvs, ContextName, Vbs, Recv, + LocalEngineID, ExtraInfo, 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, LocalEngineID, NetIf, ContextName, + Recv, LocalEngineID, ExtraInfo, + NetIf, ContextName, get(verbosity), get(sname)]) end, Recvs). %% New process -init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, Community,V,S) -> +init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, Community, V, S) -> + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, + init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, ExtraInfo, NetIf, + Community, V, S). + +init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, ExtraInfo, NetIf, + Community, V, S) -> %% Make a new Inform for each recipient; they need unique %% request-ids! put(verbosity,V), @@ -908,17 +961,26 @@ init_v2_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, Community,V,S) -> [Timeout,Retry]), InformPdu = make_v2_notif_pdu(Vbs, 'inform-request'), Msg = {send_pdu_req, 'version-2', InformPdu, {community, Community}, - [Addr], self()}, + [Addr], self(), ExtraInfo}, ?MODULE:send_inform(Addr, Timeout*10, Retry, Msg, Recv, NetIf). %% New process init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, NetIf, ContextName, V, S) -> + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, LocalEngineID = ?DEFAULT_LOCAL_ENGINE_ID, - init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID, + init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, + LocalEngineID, ExtraInfo, + NetIf, ContextName, V, S). + +init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID, NetIf, + ContextName, V, S) -> + ExtraInfo = ?DEFAULT_NOTIF_EXTRA_INFO, + init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, + LocalEngineID, ExtraInfo, NetIf, ContextName, V, S). -init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID, +init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID, ExtraInfo, NetIf, ContextName, V, S) -> %% Make a new Inform for each recipient; they need unique %% request-ids! @@ -929,7 +991,7 @@ init_v3_inform(Addr, Timeout, Retry, Vbs, Recv, LocalEngineID, InformPdu = make_v2_notif_pdu(Vbs, 'inform-request'), % Yes, v2 ContextEngineId = LocalEngineID, Msg = {send_pdu_req, 'version-3', InformPdu, - {v3, ContextEngineId, ContextName}, [Addr], self()}, + {v3, ContextEngineId, ContextName}, [Addr], self(), ExtraInfo}, ?MODULE:send_inform(Addr, Timeout*10, Retry, Msg, Recv, NetIf). send_inform(Addr, _Timeout, -1, _Msg, Recv, _NetIf) -> @@ -1017,9 +1079,27 @@ transform_taddr({?snmpUDPDomain, [A1, A2, A3, A4, P1, P2]}) -> % v2 Addr = {A1, A2, A3, A4}, Port = P1 bsl 8 + P2, {Addr, Port}; +transform_taddr({?transportDomainUdpIpv4, [A1, A2, A3, A4, P1, P2]}) -> % v2 + Addr = {A1, A2, A3, A4}, + Port = P1 bsl 8 + P2, + {Addr, Port}; +transform_taddr({?transportDomainUdpIpv6, + [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]}) -> % v2 + Addr = {A1, A2, A3, A4, A5, A6, A7, A8}, + Port = P1 bsl 8 + P2, + {Addr, Port}; transform_taddr({{?snmpUDPDomain, [A1, A2, A3, A4, P1, P2]}, _MsgData}) -> % v3 Addr = {A1, A2, A3, A4}, Port = P1 bsl 8 + P2, + {Addr, Port}; +transform_taddr({{?transportDomainUdpIpv4, [A1, A2, A3, A4, P1, P2]}, _MsgData}) -> % v3 + Addr = {A1, A2, A3, A4}, + Port = P1 bsl 8 + P2, + {Addr, Port}; +transform_taddr({{?transportDomainUdpIpv6, + [A1, A2, A3, A4, A5, A6, A7, A8, P1, P2]}, _MsgData}) -> % v3 + Addr = {A1, A2, A3, A4, A5, A6, A7, A8}, + Port = P1 bsl 8 + P2, {Addr, Port}. @@ -1069,13 +1149,14 @@ 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([{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 %%----------------------------------------------------------------- diff --git a/lib/snmp/src/agent/snmpa_usm.erl b/lib/snmp/src/agent/snmpa_usm.erl index ae584bb3c1..6f54307f9f 100644 --- a/lib/snmp/src/agent/snmpa_usm.erl +++ b/lib/snmp/src/agent/snmpa_usm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2011. 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 @@ -18,6 +18,10 @@ %% -module(snmpa_usm). +%% Avoid warning for local function error/1 clashing with autoimported BIF. +-compile({no_auto_import,[error/1]}). +%% Avoid warning for local function error/2 clashing with autoimported BIF. +-compile({no_auto_import,[error/2]}). -export([ process_incoming_msg/4, process_incoming_msg/5, generate_outgoing_msg/5, generate_outgoing_msg/6, @@ -326,7 +330,6 @@ non_authoritative(SecName, end end. - is_auth(?usmNoAuthProtocol, _, _, _, SecName, _, _, _, _) -> % 3.2.5 error(usmStatsUnsupportedSecLevels, ?usmStatsUnsupportedSecLevels_instance, SecName); % OTP-5464 @@ -609,8 +612,7 @@ authenticate_outgoing(Message, UsmSecParams, end, ?vtrace("authenticate_outgoing -> encode message only",[]), snmp_pdus:enc_message_only(Message2). - - + %%----------------------------------------------------------------- %% Auth and priv algorithms @@ -749,14 +751,19 @@ set_engine_latest_time(SnmpEngineID, EngineTime) -> %%----------------------------------------------------------------- %% Utility functions %%----------------------------------------------------------------- +-spec error(term()) -> no_return(). error(Reason) -> throw({error, Reason}). +-spec error(term(), term()) -> no_return(). error(Reason, ErrorInfo) -> throw({error, Reason, ErrorInfo}). +-spec error(term(), term(), term()) -> no_return(). error(Variable, Oid, SecName) -> error(Variable, Oid, SecName, []). + +-spec error(term(), term(), term(), [term()]) -> no_return(). error(Variable, Oid, SecName, Opts) -> Val = inc(Variable), ErrorInfo = {#varbind{oid = Oid, @@ -768,7 +775,6 @@ error(Variable, Oid, SecName, Opts) -> inc(Name) -> ets:update_counter(snmp_agent_table, Name, 1). - get_counter(Name) -> case (catch ets:lookup(snmp_agent_table, Name)) of [{_, Val}] -> @@ -776,8 +782,3 @@ get_counter(Name) -> _ -> 0 end. - - - - - diff --git a/lib/snmp/src/agent/snmpa_vacm.erl b/lib/snmp/src/agent/snmpa_vacm.erl index d17ed73ab7..dadcf32543 100644 --- a/lib/snmp/src/agent/snmpa_vacm.erl +++ b/lib/snmp/src/agent/snmpa_vacm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2009. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. 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 @@ -21,7 +21,7 @@ -export([get_mib_view/5]). -export([init/1, init/2, backup/1]). -export([delete/1, get_row/1, get_next_row/1, insert/1, insert/2, - dump_table/0]). + cleanup/0, dump_table/0]). -include("SNMPv2-TC.hrl"). -include("SNMP-VIEW-BASED-ACM-MIB.hrl"). @@ -272,14 +272,20 @@ delete(Key) -> ets:delete(snmpa_vacm, Key), dump_table(). + +cleanup() -> + ets:delete_all_objects(snmpa_vacm), + dump_table(). + dump_table(true) -> dump_table(); dump_table(_) -> ok. + dump_table() -> [{_, FName}] = ets:lookup(snmp_agent_table, snmpa_vacm_file), - TmpName = FName ++ ".tmp", + TmpName = unique_table_name(FName), case ets:tab2file(snmpa_vacm, TmpName) of ok -> case file:rename(TmpName, FName) of @@ -294,6 +300,35 @@ dump_table() -> [FName, Reason]) end. +%% This little thing is an attempt to create a "unique" filename +%% in order to minimize the risk of two processes at the same +%% time dumping the table. +unique_table_name(Pre) -> + %% We want something that is guaranteed to be unique, + %% therefor we use erlang:now() instead of os:timestamp() + unique_table_name(Pre, erlang:now()). + +unique_table_name(Pre, {_A, _B, C} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY, MM, DD} = Date, + {Hour, Min, Sec} = Time, + FormatDate = + io_lib:format("~.4w~.2.0w~.2.0w_~.2.0w~.2.0w~.2.0w_~w", + [YYYY, MM, DD, Hour, Min, Sec, round(C/1000)]), + unique_table_name2(Pre, FormatDate). + +unique_table_name2(Pre, FormatedDate) -> + PidPart = unique_table_name_pid(), + lists:flatten(io_lib:format("~s.~s~s.tmp", [Pre, PidPart, FormatedDate])). + +unique_table_name_pid() -> + case string:tokens(pid_to_list(self()), [$<,$.,$>]) of + [A, B, C] -> + A ++ B ++ C ++ "."; + _ -> + "" + end. + %%----------------------------------------------------------------- %% Alg. |