From 768a6d38597b8bedf6551ad2e6472b2965765dd2 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Wed, 9 Apr 2014 10:29:00 +0200 Subject: Rewrite agent configuration parsing --- lib/snmp/src/agent/snmp_community_mib.erl | 71 +++-- lib/snmp/src/agent/snmp_framework_mib.erl | 55 ++-- lib/snmp/src/agent/snmp_notification_mib.erl | 24 +- lib/snmp/src/agent/snmp_standard_mib.erl | 23 +- lib/snmp/src/agent/snmp_target_mib.erl | 172 +++++++---- lib/snmp/src/agent/snmp_user_based_sm_mib.erl | 14 +- lib/snmp/src/agent/snmp_view_based_acm_mib.erl | 23 +- lib/snmp/src/agent/snmpa_conf.erl | 96 ++++-- lib/snmp/src/agent/snmpa_mpd.erl | 39 ++- lib/snmp/src/manager/snmpm_config.erl | 10 +- lib/snmp/src/misc/snmp_conf.erl | 406 +++++++++++++++++++------ lib/snmp/src/misc/snmp_config.erl | 143 ++++++--- lib/snmp/test/snmp_agent_test_lib.erl | 26 +- 13 files changed, 793 insertions(+), 309 deletions(-) (limited to 'lib') diff --git a/lib/snmp/src/agent/snmp_community_mib.erl b/lib/snmp/src/agent/snmp_community_mib.erl index 7bdd500727..12a0ec97c2 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-2012. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -31,6 +31,7 @@ -include("snmpa_internal.hrl"). -include("SNMP-COMMUNITY-MIB.hrl"). -include("SNMP-TARGET-MIB.hrl"). +-include("SNMPv2-TM.hrl"). -include("SNMPv2-TC.hrl"). -include("snmp_types.hrl"). @@ -129,10 +130,11 @@ read_community_config_files(Dir) -> [FileName, D, Reason]), ok end, - Filter = fun(Comms) -> Comms end, - Check = fun(Entry) -> check_community(Entry) end, + Order = fun snmp_conf:no_order/2, + Filter = fun snmp_conf:no_filter/1, + Check = fun(Entry, State) -> {check_community(Entry), State} end, [Comms] = - snmp_conf:read_files(Dir, [{Gen, Filter, Check, "community.conf"}]), + snmp_conf:read_files(Dir, [{FileName, Gen, Order, Check, Filter}]), Comms. check_community({Index, CommunityName, SecName, CtxName, TransportTag}) -> @@ -192,7 +194,7 @@ add_community(Idx, CommName, SecName, EngineId, CtxName, TransportTag) -> do_add_community(Community). do_add_community(Community) -> - case (catch check_community(Community)) of + try check_community(Community) of {ok, Row} -> Key = element(1, Row), case table_cre_row(snmpCommunityTable, Key, Row) of @@ -201,11 +203,12 @@ do_add_community(Community) -> {ok, Key}; false -> {error, create_failed} - end; + end + catch {error, Reason} -> {error, Reason}; - Error -> - {error, Error} + Class:Reason -> + {error, {Class, Reason, erlang:get_stacktrace()}} end. %% FIXME: does not work with mnesia @@ -506,7 +509,12 @@ snmpTargetAddrExtTable(get_next, RowIndex, Cols) -> NCols = conv1(Cols), conv2(next(snmpTargetAddrExtTable, RowIndex, NCols)); snmpTargetAddrExtTable(set, RowIndex, Cols0) -> - case (catch verify_snmpTargetAddrExtTable_cols(Cols0, [])) of + case + (catch verify_snmpTargetAddrExtTable_cols( + Cols0, + get_snmpTargetAddrTDomain(RowIndex, Cols0), + [])) + of {ok, Cols} -> NCols = conv3(Cols), snmp_generic:table_func(set, RowIndex, NCols, @@ -515,7 +523,11 @@ snmpTargetAddrExtTable(set, RowIndex, Cols0) -> Error end; snmpTargetAddrExtTable(is_set_ok, RowIndex, Cols0) -> - case (catch verify_snmpTargetAddrExtTable_cols(Cols0, [])) of + case (catch verify_snmpTargetAddrExtTable_cols( + Cols0, + get_snmpTargetAddrTDomain(RowIndex, Cols0), + [])) + of {ok, Cols} -> NCols = conv3(Cols), snmp_generic:table_func(is_set_ok, RowIndex, NCols, @@ -525,29 +537,49 @@ snmpTargetAddrExtTable(is_set_ok, RowIndex, Cols0) -> end. -verify_snmpTargetAddrExtTable_cols([], Cols) -> + +get_snmpTargetAddrTDomain(RowIndex, Col) -> + case + get( + snmpTargetAddrTable, RowIndex, + [?snmpTargetAddrRowStatus,?snmpTargetAddrTDomain]) + of + [{value,?snmpTargetAddrRowStatus_active},ValueTDomain] -> + case ValueTDomain of + {value,TDomain} -> + TDomain; + _ -> + ?snmpUDPDomain + end; + _ -> + wrongValue(Col) + end. + + + +verify_snmpTargetAddrExtTable_cols([], _TDomain, Cols) -> {ok, lists:reverse(Cols)}; -verify_snmpTargetAddrExtTable_cols([{Col, Val0}|Cols], Acc) -> - Val = verify_snmpTargetAddrExtTable_col(Col, Val0), - verify_snmpTargetAddrExtTable_cols(Cols, [{Col, Val}|Acc]). +verify_snmpTargetAddrExtTable_cols([{Col, Val0}|Cols], TDomain, Acc) -> + Val = verify_snmpTargetAddrExtTable_col(Col, TDomain, Val0), + verify_snmpTargetAddrExtTable_cols(Cols, TDomain, [{Col, Val}|Acc]). -verify_snmpTargetAddrExtTable_col(?snmpTargetAddrTMask, []) -> +verify_snmpTargetAddrExtTable_col(?snmpTargetAddrTMask, _TDomain, []) -> []; -verify_snmpTargetAddrExtTable_col(?snmpTargetAddrTMask, TMask) -> - case (catch snmp_conf:check_taddress(TMask)) of +verify_snmpTargetAddrExtTable_col(?snmpTargetAddrTMask, TDomain, TMask) -> + case (catch snmp_conf:check_taddress(TDomain, TMask)) of ok -> TMask; _ -> wrongValue(?snmpTargetAddrTMask) end; -verify_snmpTargetAddrExtTable_col(?snmpTargetAddrMMS, MMS) -> +verify_snmpTargetAddrExtTable_col(?snmpTargetAddrMMS, _TDomain, MMS) -> case (catch snmp_conf:check_packet_size(MMS)) of ok -> MMS; _ -> wrongValue(?snmpTargetAddrMMS) end; -verify_snmpTargetAddrExtTable_col(_, Val) -> +verify_snmpTargetAddrExtTable_col(_, _TDomain, Val) -> Val. db(snmpTargetAddrExtTable) -> db(snmpTargetAddrTable); @@ -583,6 +615,7 @@ conv3([{Idx, Val}|T]) -> [{Idx+10, Val} | conv3(T)]; conv3([]) -> []. + get(Name, RowIndex, Cols) -> snmp_generic:handle_table_get(db(Name), RowIndex, Cols, foi(Name)). diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl index cc191bd956..84f39df228 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-2012. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -51,7 +51,7 @@ set_engine_boots/1, set_engine_time/1, table_next/2, check_status/3]). -export([add_context/1, delete_context/1]). --export([check_agent/1, check_context/1]). +-export([check_agent/1, check_agent/2, check_context/1, order_agent/2]). %%----------------------------------------------------------------- @@ -115,23 +115,22 @@ do_configure(Dir) -> read_internal_config_files(Dir) -> ?vdebug("read context config file",[]), - Gen = fun(D, Reason) -> - convert_context(D, Reason) - end, - Filter = fun(Contexts) -> Contexts end, - Check = fun(Entry) -> check_context(Entry) end, - [Ctxs] = snmp_conf:read_files(Dir, [{Gen, Filter, Check, "context.conf"}]), + Gen = fun gen_context/2, + Order = fun snmp_conf:no_order/2, + Filter = fun snmp_conf:no_filter/1, + Check = fun(Entry, State) -> {check_context(Entry), State} end, + [Ctxs] = + snmp_conf:read_files + (Dir, [{"context.conf", Gen, Order, Check, Filter}]), Ctxs. - read_agent(Dir) -> ?vdebug("read agent config file", []), - FileName = "agent.conf", - Check = fun(Entry) -> check_agent(Entry) end, + FileName = "agent.conf", File = filename:join(Dir, FileName), - Agent = + Agent = try - snmp_conf:read(File, Check) + snmp_conf:read(File, fun order_agent/2, fun check_agent/2) catch throw:{error, Reason} -> error({failed_reading_config_file, Dir, FileName, Reason}) @@ -155,14 +154,15 @@ sort_agent(L) -> %%----------------------------------------------------------------- %% Generate a context.conf file. %%----------------------------------------------------------------- -convert_context(Dir, _Reason) -> +gen_context(Dir, _Reason) -> config_err("missing context.conf file => generating a default file", []), File = filename:join(Dir, "context.conf"), case file:open(File, [write]) of {ok, Fid} -> ok = io:format(Fid, "~s\n", [context_header()]), ok = io:format(Fid, "%% The default context\n\"\".\n", []), - file:close(Fid); + file:close(Fid), + []; {error, Reason} -> file:delete(File), error({failed_creating_file, File, Reason}) @@ -196,9 +196,21 @@ check_context(Context) -> %% Agent %% {Name, Value}. %%----------------------------------------------------------------- -check_agent({intAgentIpAddress, Value}) -> +check_agent({intAgentTransportDomain, D}, Domain) -> + case Domain of + undefined -> + {snmp_conf:check_domain(D), D}; + _ -> + error({invalid_agent_attribute, D}) + end; +check_agent({intAgentTransportAddress, Address}, Domain) -> + {snmp_conf:check_address(Domain, Address), Domain}; +check_agent(Entry, Domain) -> + {check_agent(Entry), Domain}. + +check_agent({intAgentIpAddress, Value}) -> % Obsoleted snmp_conf:check_ip(Value); -check_agent({intAgentUDPPort, Value}) -> +check_agent({intAgentUDPPort, Value}) -> % Obsoleted snmp_conf:check_integer(Value); %% This one is kept for backwards compatibility check_agent({intAgentMaxPacketSize, Value}) -> @@ -210,6 +222,15 @@ check_agent({snmpEngineID, Value}) -> check_agent(X) -> error({invalid_agent_attribute, X}). +%% Ordering function to sort intAgentTransportDomain first +%% hence before intAgentTransportAddress +order_agent({intAgentTransportDomain, _}, {intAgentTransportDomain, _}) -> + true; %% Less than or equal +order_agent(_, {intAgentTransportDomain, _}) -> + false; %% Greater than +order_agent(_, _) -> + true. %% Less than or equal + maybe_create_table(Name) -> case snmpa_local_db:table_exists(db(Name)) of diff --git a/lib/snmp/src/agent/snmp_notification_mib.erl b/lib/snmp/src/agent/snmp_notification_mib.erl index 37e09f5d3e..31c7735226 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-2012. All Rights Reserved. +%% Copyright Ericsson AB 1998-2014. 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 @@ -106,17 +106,19 @@ do_reconfigure(Dir) -> read_notify_config_files(Dir) -> ?vdebug("read notify config file",[]), FileName = "notify.conf", - Gen = fun(D, Reason) -> - info_msg("failed reading config file ~s" - "~n Config Dir: ~s" - "~n Reason: ~p", - [FileName, D, Reason]), - ok - end, - Filter = fun(Notifs) -> Notifs end, - Check = fun(Entry) -> check_notify(Entry) end, + Gen = + fun (D, Reason) -> + info_msg("failed reading config file ~s" + "~n Config Dir: ~s" + "~n Reason: ~p", + [FileName, D, Reason]), + ok + end, + Order = fun snmp_conf:no_order/2, + Filter = fun snmp_conf:no_filter/1, + Check = fun (Entry, State) -> {check_notify(Entry), State} end, [Notifs] = - snmp_conf:read_files(Dir, [{Gen, Filter, Check, "notify.conf"}]), + snmp_conf:read_files(Dir, [{FileName, Gen, Order, Check, Filter}]), Notifs. check_notify({Name, Tag, Type}) -> diff --git a/lib/snmp/src/agent/snmp_standard_mib.erl b/lib/snmp/src/agent/snmp_standard_mib.erl index 766b75022b..aace3fd413 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-2012. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -152,16 +152,19 @@ do_reconfigure(Dir) -> %%----------------------------------------------------------------- read_standard(Dir) -> ?vdebug("check standard config file",[]), - FileName = "standard.conf", - Gen = fun(D, Reason) -> - throw({error, {failed_reading_config_file, - D, FileName, - list_dir(Dir), Reason}}) - end, - Filter = fun(Standard) -> sort_standard(Standard) end, - Check = fun(Entry) -> check_standard(Entry) end, + FileName = "standard.conf", + Gen = + fun (D, Reason) -> + throw( + {error, + {failed_reading_config_file, + D, FileName, list_dir(Dir), Reason}}) + end, + Order = fun snmp_conf:no_order/2, + Check = fun (Entry, State) -> {check_standard(Entry), State} end, + Filter = fun sort_standard/1, [Standard] = - snmp_conf:read_files(Dir, [{Gen, Filter, Check, FileName}]), + snmp_conf:read_files(Dir, [{FileName, Gen, Order, Check, Filter}]), Standard. list_dir(Dir) -> diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl index b01d536caa..6dd3b6e23a 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-2012. All Rights Reserved. +%% Copyright Ericsson AB 1998-2014. 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 @@ -133,18 +133,22 @@ do_reconfigure(Dir) -> read_target_config_files(Dir) -> ?vdebug("check target address and parameter config file(s)",[]), - TAGen = fun(_D, _Reason) -> ok end, - TAFilter = fun(Addr) -> Addr end, - TACheck = fun(Entry) -> check_target_addr(Entry) end, - TPGen = fun(_D, _Reason) -> ok end, - TPFilter = fun(Params) -> Params end, - TPCheck = fun(Entry) -> check_target_params(Entry) end, + TAName = "target_addr.conf", + TACheck = fun (Entry, State) -> {check_target_addr(Entry), State} end, + + TPName = "target_params.conf", + TPCheck = fun (Entry, State) -> {check_target_params(Entry), State} end, + + NoGen = fun snmp_conf:no_gen/2, + NoOrder = fun snmp_conf:no_order/2, + NoFilter = fun snmp_conf:no_filter/1, [Addrs, Params] = - snmp_conf:read_files(Dir, - [{TAGen, TAFilter, TACheck, "target_addr.conf"}, - {TPGen, TPFilter, TPCheck, "target_params.conf"}]), + snmp_conf:read_files( + Dir, + [{TAName, NoGen, NoOrder, TACheck, NoFilter}, + {TPName, NoGen, NoOrder, TPCheck, NoFilter}]), {Addrs, Params}. @@ -154,80 +158,142 @@ read_target_config_files(Dir) -> %% TMask, MMS} %%----------------------------------------------------------------- -check_target_addr({Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, - Params, EngineId, TMask, MMS}) -> +check_target_addr( + {Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS}) -> % Arity 11 + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS); +check_target_addr( + {Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS}) % Arity 10 + when is_atom(Domain) -> + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS); +check_target_addr( + {Name, Ip, Udp, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS}) -> % Arity 10 + Domain = default_domain(), + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, TMask, MMS); +check_target_addr( + {Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId}) % Arity 8 + when is_atom(Domain) -> + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId); +check_target_addr( + {Name, Ip, Udp, Timeout, RetryCount, TagList, Params, + EngineId}) -> % Arity 8 + Domain = default_domain(), + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId); +%% Use dummy engine id if the old style is found +check_target_addr( + {Name, Domain, Address, Timeout, RetryCount, TagList, Params}) % Arity 7 + when is_atom(Domain) -> + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params); +check_target_addr( + {Name, Ip, Udp, Timeout, RetryCount, TagList, Params}) -> % Arity 7 + Domain = default_domain(), + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params); +%% Use dummy engine id if the old style is found +check_target_addr( + {Name, Domain, Address, Timeout, RetryCount, TagList, Params, + TMask, MMS}) % Arity 9 + when is_atom(Domain) -> + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, TMask, MMS); +check_target_addr( + {Name, Ip, Udp, Timeout, RetryCount, TagList, Params, + TMask, MMS}) -> % Arity 9 + Domain = default_domain(), + Address = {Ip, Udp}, + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, TMask, MMS); +check_target_addr(X) -> + error({invalid_target_addr, X}). + +check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params) -> % Arity 7 + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + "dummy"). +%% +check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId) -> % Arity 8 + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, [], 2048). +%% +check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + TMask, MMS) -> % Arity 9 + check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + "dummy", TMask, MMS). +%% +check_target_addr( + Name, Domain, Address, Timeout, RetryCount, TagList, Params, + EngineId, Mask, MMS) -> % Arity 10 ?vtrace("check target address with:" "~n Name: ~s" "~n Domain: ~p" - "~n Ip: ~p" - "~n Udp: ~p" + "~n Address: ~p" "~n Timeout: ~p" "~n RetryCount: ~p" "~n TagList: ~p" "~n Params: ~p" "~n EngineId: ~p" - "~n TMask: ~p" + "~n Mask: ~p" "~n MMS: ~p", - [Name, - Domain, Ip, Udp, + [Name, Domain, Address, Timeout, RetryCount, - TagList, Params, EngineId, TMask, MMS]), + TagList, Params, EngineId, Mask, MMS]), snmp_conf:check_string(Name,{gt,0}), snmp_conf:check_domain(Domain), - snmp_conf:check_ip(Domain, Ip), - snmp_conf:check_integer(Udp, {gt, 0}), + snmp_conf:check_address(Domain, Address), 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), - TAddress = snmp_conf:mk_taddress(Domain, Ip, Udp), + check_mask(Domain, Mask), TDomain = snmp_conf:mk_tdomain(Domain), - check_tmask(TDomain, TMask, TAddress), + TAddress = snmp_conf:mk_taddress(Domain, Address), + TMask = snmp_conf:mk_taddress(Domain, Mask), snmp_conf:check_packet_size(MMS), ?vtrace("check target address done",[]), 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, - Params, EngineId, [], 2048}); -%% Use dummy engine id if the old style is found -check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, Params}) -> - check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, - Params, "dummy", [], 2048}); -%% Use dummy engine id if the old style is found -check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, Params, - TMask, MMS}) -> - check_target_addr({Name, Ip, Udp, Timeout, RetryCount, TagList, - Params, "dummy", TMask, MMS}); -check_target_addr(X) -> - error({invalid_target_addr, X}). - + {ok, Addr}. check_engine_id(discovery) -> ok; check_engine_id(EngineId) -> snmp_conf:check_string(EngineId). - -check_tmask(_TDomain, [], _TAddress) -> +check_mask(_Domain, []) -> ok; -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}}). - +check_mask(Domain, Mask) -> + try snmp_conf:check_address(Domain, Mask) + catch + {error, {invalid_address, Info}} -> + {error, {invalid_mask, Info}} + end. %%----------------------------------------------------------------- %% TargetParams 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 223d3f7218..69dce337ba 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-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -137,18 +137,20 @@ do_reconfigure(Dir) -> read_usm_config_files(Dir) -> ?vdebug("read usm config file",[]), - Gen = fun(D, Reason) -> generate_usm(D, Reason) end, - Filter = fun(Usms) -> Usms end, - Check = fun(Entry) -> check_usm(Entry) end, + Gen = fun (D, Reason) -> generate_usm(D, Reason) end, + Order = fun snmp_conf:no_order/2, + Check = fun (Entry, State) -> {check_usm(Entry), State} end, + Filter = fun snmp_conf:no_filter/1, [Usms] = - snmp_conf:read_files(Dir, [{Gen, Filter, Check, "usm.conf"}]), + snmp_conf:read_files(Dir, [{"usm.conf", Gen, Order, Check, Filter}]), Usms. generate_usm(Dir, _Reason) -> info_msg("Incomplete configuration. Generating empty usm.conf.", []), USMFile = filename:join(Dir, "usm.conf"), - ok = file:write_file(USMFile, list_to_binary([])). + ok = file:write_file(USMFile, list_to_binary([])), + []. check_usm({EngineID, Name, SecName, Clone, AuthP, AuthKeyC, OwnAuthKeyC, 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 c0177b1cea..722bd7ac5b 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-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. 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 @@ -123,15 +123,18 @@ do_reconfigure(Dir) -> read_vacm_config_files(Dir) -> ?vdebug("read vacm config file",[]), - Gen = fun(_D, _Reason) -> ok end, - Filter = fun(Vacms) -> - Sec2Group = [X || {vacmSecurityToGroup, X} <- Vacms], - Access = [X || {vacmAccess, X} <- Vacms], - View = [X || {vacmViewTreeFamily, X} <- Vacms], - {Sec2Group, Access, View} - end, - Check = fun(Entry) -> check_vacm(Entry) end, - [Vacms] = snmp_conf:read_files(Dir, [{Gen, Filter, Check, "vacm.conf"}]), + Gen = fun snmp_conf:no_gen/2, + Order = fun snmp_conf:no_order/2, + Check = fun (Entry, State) -> {check_vacm(Entry), State} end, + Filter = + fun (Vacms) -> + Sec2Group = [X || {vacmSecurityToGroup, X} <- Vacms], + Access = [X || {vacmAccess, X} <- Vacms], + View = [X || {vacmViewTreeFamily, X} <- Vacms], + {Sec2Group, Access, View} + end, + [Vacms] = + snmp_conf:read_files(Dir, [{"vacm.conf", Gen, Order, Check, Filter}]), Vacms. %%----------------------------------------------------------------- diff --git a/lib/snmp/src/agent/snmpa_conf.erl b/lib/snmp/src/agent/snmpa_conf.erl index c17a6abbd7..a405987c8a 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-2011. All Rights Reserved. +%% Copyright Ericsson AB 2006-2014. 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 @@ -123,21 +123,24 @@ append_agent_config(Dir, Conf) read_agent_config(Dir) -> - Verify = fun(Entry) -> verify_agent_conf_entry(Entry) end, - read_config_file(Dir, "agent.conf", Verify). + Order = fun snmp_framework_mib:order_agent/2, + Check = fun check_agent_conf_entry/2, + read_config_file(Dir, "agent.conf", Order, Check). - -verify_agent_conf([]) -> + +verify_agent_conf(Conf) -> + verify_agent_conf(Conf, undefined). +%% +verify_agent_conf([], _) -> ok; -verify_agent_conf([H|T]) -> - verify_agent_conf_entry(H), - verify_agent_conf(T); -verify_agent_conf(X) -> +verify_agent_conf([H|T], State) -> + {_, NewState} = check_agent_conf_entry(H, State), + verify_agent_conf(T, NewState); +verify_agent_conf(X, _) -> error({bad_agent_config, X}). -verify_agent_conf_entry(Entry) -> - ok = snmp_framework_mib:check_agent(Entry), - ok. +check_agent_conf_entry(Entry, State) -> + {ok, _NewState} = snmp_framework_mib:check_agent(Entry, State). write_agent_conf(Fd, "", Conf) -> write_agent_conf(Fd, Conf); @@ -204,8 +207,12 @@ append_context_config(Dir, Conf) read_context_config(Dir) -> - Verify = fun(Entry) -> verify_context_conf_entry(Entry) end, - read_config_file(Dir, "context.conf", Verify). + Order = fun snmp_conf:no_order/2, + Verify = + fun (Entry, State) -> + {verify_context_conf_entry(Entry), State} + end, + read_config_file(Dir, "context.conf", Order, Verify). verify_context_conf([]) -> @@ -286,8 +293,12 @@ append_community_config(Dir, Conf) read_community_config(Dir) -> - Verify = fun(Entry) -> verify_community_conf_entry(Entry) end, - read_config_file(Dir, "community.conf", Verify). + Order = fun snmp_conf:no_order/2, + Verify = + fun (Entry, State) -> + {verify_community_conf_entry(Entry), State} + end, + read_config_file(Dir, "community.conf", Order, Verify). verify_community_conf([]) -> @@ -358,8 +369,12 @@ append_standard_config(Dir, Conf) read_standard_config(Dir) -> - Verify = fun(Entry) -> verify_standard_conf_entry(Entry) end, - read_config_file(Dir, "standard.conf", Verify). + Order = fun snmp_conf:no_order/2, + Verify = + fun (Entry, State) -> + {verify_standard_conf_entry(Entry), State} + end, + read_config_file(Dir, "standard.conf", Order, Verify). verify_standard_conf([]) -> @@ -520,8 +535,12 @@ append_target_addr_config(Dir, Conf) read_target_addr_config(Dir) -> - Verify = fun(Entry) -> verify_target_addr_conf_entry(Entry) end, - read_config_file(Dir, "target_addr.conf", Verify). + Order = fun snmp_conf:no_order/2, + Verify = + fun (Entry, State) -> + {verify_target_addr_conf_entry(Entry), State} + end, + read_config_file(Dir, "target_addr.conf", Order, Verify). verify_target_addr_conf([]) -> @@ -626,8 +645,12 @@ append_target_params_config(Dir, Conf) read_target_params_config(Dir) -> - Verify = fun(Entry) -> verify_target_params_conf_entry(Entry) end, - read_config_file(Dir, "target_params.conf", Verify). + Order = fun snmp_conf:no_order/2, + Verify = + fun (Entry, State) -> + {verify_target_params_conf_entry(Entry), State} + end, + read_config_file(Dir, "target_params.conf", Order, Verify). verify_target_params_conf([]) -> @@ -698,8 +721,12 @@ append_notify_config(Dir, Conf) read_notify_config(Dir) -> - Verify = fun(Entry) -> verify_notify_conf_entry(Entry) end, - read_config_file(Dir, "notify.conf", Verify). + Order = fun snmp_conf:no_order/2, + Verify = + fun (Entry, State) -> + {verify_notify_conf_entry(Entry), State} + end, + read_config_file(Dir, "notify.conf", Order, Verify). verify_notify_conf([]) -> @@ -794,8 +821,12 @@ append_usm_config(Dir, Conf) read_usm_config(Dir) -> - Verify = fun(Entry) -> verify_usm_conf_entry(Entry) end, - read_config_file(Dir, "usm.conf", Verify). + Order = fun snmp_conf:no_order/2, + Verify = + fun (Entry, State) -> + {verify_usm_conf_entry(Entry), State} + end, + read_config_file(Dir, "usm.conf", Order, Verify). verify_usm_conf([]) -> @@ -903,8 +934,12 @@ append_vacm_config(Dir, Conf) read_vacm_config(Dir) -> - Verify = fun(Entry) -> verify_vacm_conf_entry(Entry) end, - read_config_file(Dir, "vacm.conf", Verify). + Order = fun snmp_conf:no_order/2, + Verify = + fun (Entry, State) -> + {verify_vacm_conf_entry(Entry), State} + end, + read_config_file(Dir, "vacm.conf", Order, Verify). verify_vacm_conf([]) -> @@ -958,8 +993,8 @@ write_config_file(Dir, File, Verify, Write) -> append_config_file(Dir, File, Verify, Write) -> snmp_config:append_config_file(Dir, File, Verify, Write). -read_config_file(Dir, File, Verify) -> - snmp_config:read_config_file(Dir, File, Verify). +read_config_file(Dir, File, Order, Check) -> + snmp_config:read_config_file(Dir, File, Order, Check). %% ---- config file utility functions ---- @@ -972,6 +1007,5 @@ header() -> "~2.2.0w:~2.2.0w:~2.2.0w\n", [?MODULE, ?version, Y, Mo, D, H, Mi, S]). - error(R) -> throw({error, R}). diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl index 11ae806866..9bb4556788 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-2013. All Rights Reserved. +%% Copyright Ericsson AB 1997-2014. 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 @@ -183,11 +183,30 @@ discarded_pdu(Variable) -> inc(Variable). %%----------------------------------------------------------------- %% Handles a Community based message (v1 or v2c). %%----------------------------------------------------------------- -v1_v2c_proc(Vsn, NoteStore, Community, Domain, - {Ip, Udp}, LocalEngineID, - Data, HS, Log, Packet) -> +v1_v2c_proc( + Vsn, NoteStore, Community, Domain, Address, + LocalEngineID, Data, HS, Log, Packet) -> + try snmp_conf:check_domain(Domain) of + ok -> + try snmp_conf:check_address(Domain, Address) of + ok -> + v1_v2c_proc_dec( + Vsn, NoteStore, Community, Domain, Address, + LocalEngineID, Data, HS, Log, Packet) + catch + _ -> + {discarded, {badarg, Address}} + end + catch + _ -> + {discarded, {badarg, Domain}} + end. + +v1_v2c_proc_dec( + Vsn, NoteStore, Community, Domain, Address, + LocalEngineID, Data, HS, Log, Packet) -> TDomain = snmp_conf:mk_tdomain(Domain), - TAddress = snmp_conf:mk_taddress(Domain, Ip, Udp), + TAddress = snmp_conf:mk_taddress(Domain, Address), AgentMS = get_engine_max_message_size(LocalEngineID), MgrMS = snmp_community_mib:get_target_addr_ext_mms(TDomain, TAddress), PduMS = case MgrMS of @@ -214,7 +233,7 @@ v1_v2c_proc(Vsn, NoteStore, Community, Domain, case Pdu#pdu.type of 'set-request' -> %% Check if this message has already been processed - Key = {agent, Ip, ReqId}, + Key = {agent, {Domain, Address}, ReqId}, case snmp_note_store:get_note(NoteStore, Key) of undefined -> %% Set the processed note _after_ pdu processing. @@ -236,13 +255,7 @@ v1_v2c_proc(Vsn, NoteStore, Community, Domain, {discarded, Reason}; _TrapPdu -> {discarded, trap_pdu} - end; -v1_v2c_proc(_Vsn, _NoteStore, _Community, snmpUDPDomain, TAddress, - _LocalEngineID, _Data, _HS, _Log, _Packet) -> - {discarded, {badarg, TAddress}}; -v1_v2c_proc(_Vsn, _NoteStore, _Community, TDomain, _TAddress, - _LocalEngineID, _Data, _HS, _Log, _Packet) -> - {discarded, {badarg, TDomain}}. + end. sec_model('version-1') -> ?SEC_V1; sec_model('version-2') -> ?SEC_V2C. diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 2101ad46e1..43d394e9d9 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2013. All Rights Reserved. +%% Copyright Ericsson AB 2004-2014. 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 @@ -1666,7 +1666,7 @@ init_agent_default(Item, Val) when Item =/= user_id -> read_agents_config_file(Dir) -> - Check = fun(C) -> check_agent_config2(C) end, + Check = fun(C, S) -> {check_agent_config2(C), S} end, case read_file(Dir, "agents.conf", Check, []) of {ok, Conf} -> Conf; @@ -1837,7 +1837,7 @@ verify_agent2([Bad|_], _VerifiedConf) -> read_users_config_file(Dir) -> - Check = fun(C) -> check_user_config(C) end, + Check = fun(C, S) -> {check_user_config(C), S} end, case read_file(Dir, "users.conf", Check, []) of {ok, Conf} -> Conf; @@ -1950,7 +1950,7 @@ verify_user_agent_config(Conf) -> end. read_usm_config_file(Dir) -> - Check = fun(C) -> check_usm_user_config(C) end, + Check = fun(C, S) -> {check_usm_user_config(C), S} end, case read_file(Dir, "usm.conf", Check, []) of {ok, Conf} -> Conf; @@ -2139,7 +2139,7 @@ is_crypto_supported(Func) -> read_manager_config_file(Dir) -> - Check = fun(Conf) -> check_manager_config(Conf) end, + Check = fun(Conf, State) -> {check_manager_config(Conf), State} end, case read_file(Dir, "manager.conf", Check) of {ok, Conf} -> ?d("read_manager_config_file -> ok: " diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl index 46625989d5..c52b4bb6fb 100644 --- a/lib/snmp/src/misc/snmp_conf.erl +++ b/lib/snmp/src/misc/snmp_conf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -25,7 +25,8 @@ %% External exports %% Avoid warning for local function error/1 clashing with autoimported BIF. -compile({no_auto_import,[error/1]}). --export([read_files/2, read/2]). +-export([read_files/2, no_gen/2, no_order/2, no_filter/1]). +-export([read/2, read/3]). %% Basic (type) check functions -export([check_mandatory/2, @@ -43,9 +44,10 @@ check_tdomain/1, mk_tdomain/1, which_domain/1, - check_ip/1, check_ip/2, - check_taddress/1, check_taddress/2, - mk_taddress/3, + check_ip/1, check_ip/2, + check_address/2, + check_taddress/2, + mk_taddress/2, mk_taddress/3, check_packet_size/1, @@ -70,17 +72,53 @@ -include("snmp_verbosity.hrl"). +-define(is_word(P), (((P) band (bnot 65535)) =:= 0)). +-define(is_word(P0, P1), ((((P0) bor (P1)) band (bnot 255)) =:= 0)). + +mk_word(B0, B1) -> ((B0) bsl 8) bor (B1). +mk_bytes(W) -> [(W) bsr 8,(W) band 255]. + +-define( + is_ipv4_addr(A0, A1, A2, A3), + ((((A0) bor (A1) bor (A2) bor (A3)) band (bnot 255)) =:= 0)). + +-define( + is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ((((A0) bor (A1) bor (A2) bor (A3) bor (A4) bor (A5) bor (A6) bor (A7)) + band (bnot 65535)) =:= 0)). +-define( + is_ipv6_addr( + A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15), + ((((A0) bor (A1) bor (A2) bor (A3) bor + (A4) bor (A5) bor (A6) bor (A7) bor + (A8) bor (A9) bor (A10) bor (A11) bor + (A12) bor (A13) bor (A14) bor (A15)) + band (bnot 65535)) =:= 0)). + + %%----------------------------------------------------------------- %% read_files(Dir, Files) -> Configs %% Dir - string() - Full path to the config dir. -%% Files - [{Gen, Filter, Check, FileName}] +%% Files - [{FileName, Gen, Order, Check, Filter}] +%% FileName - string() - Name of the config file. %% Gen - function/2 - In case of failure when reading the config file, %% this function is called to either generate a %% default file or issue the error. -%% Filter - function/1 - Filters all the config entries read from the file -%% Check - function/1 - Check each entry as they are read from the file. -%% FileName - string() - Name of the config file. +%% Returns a generated config list corresponding +%% to the written file. +%% (Dir, Error) -> Configs. +%% Order - function/2 - An ordering function that is used to process +%% the read config entries using lists:sort/2. +%% Returns true if arg 1 compares less than or +%% equal to arg 2, false otherwise. +%% Check - function/2 - Check each entry as they are read from the file. +%% (Entry, State) -> +%% {ok,NewState} | {{ok,NewEntry},NewState} | +%% throw(Error) +%% State =:= 'undefined' the first time. +%% Filter - function/1 - Process all the config entries read from the file +%% (Configs) -> [config_entry()]. %% Configs - [config_entry()] %% config_entry() - term() @@ -89,24 +127,122 @@ read_files(Dir, Files) when is_list(Dir) andalso is_list(Files) -> read_files(_Dir, [], Res) -> lists:reverse(Res); -read_files(Dir, [{Gen, Filter, Check, FileName}|Files], Res) - when is_function(Filter) andalso - is_function(Check) andalso - is_list(FileName) -> - ?vdebug("read_files -> entry with" - "~n FileName: ~p", [FileName]), +read_files(Dir, [{FileName, Gen, Order, Check, Filter}|Files], Res) + when is_list(FileName), + is_function(Gen), + is_function(Order), + is_function(Check), + is_function(Filter) -> + ?vdebug("read_files -> entry with~n" + " FileName: ~p", [FileName]), File = filename:join(Dir, FileName), - case file:read_file_info(File) of - {ok, _} -> - Confs = read(File, Check), - read_files(Dir, Files, [Filter(Confs)|Res]); - {error, R} -> - ?vlog("failed reading file info for ~s: " - "~n ~p", [FileName, R]), - Gen(Dir, R), - read_files(Dir, Files, [Filter([])|Res]) + Confs = + case file:read_file_info(File) of + {ok,_} -> + read(File, Order, Check); + {error, R} -> + ?vlog("failed reading file info for ~s: ~n" + " ~p", [FileName, R]), + Gen(Dir, R) + end, + read_files(Dir, Files, [Filter(Confs)|Res]). +%% %% +%% %% XXX remove +%% %% +%% %% read_files(Dir, Files) -> Configs +%% %% Dir - string() - Full path to the config dir. +%% %% Files - [{Gen, Filter, Check, FileName}] +%% %% Gen - function/2 - In case of failure when reading the config file, +%% %% this function is called to either generate a +%% %% default file or issue the error. +%% %% Filter - function/1 - Filters all the config entries read from the file +%% %% Check - function/1 - Check each entry as they are read from the file. +%% %% FileName - string() - Name of the config file. +%% %% Configs - [config_entry()] +%% %% config_entry() - term() +%% +%% read_files(Dir, [{Gen, Filter, Check, FileName}|Files], Res) +%% when is_function(Filter) andalso +%% is_function(Check) andalso +%% is_list(FileName) -> +%% ?vdebug("read_files -> entry with" +%% "~n FileName: ~p", [FileName]), +%% File = filename:join(Dir, FileName), +%% case file:read_file_info(File) of +%% {ok, _} -> +%% Confs = read(File, Check), +%% read_files(Dir, Files, [Filter(Confs)|Res]); +%% {error, R} -> +%% ?vlog("failed reading file info for ~s: " +%% "~n ~p", [FileName, R]), +%% Gen(Dir, R), +%% read_files(Dir, Files, [Filter([])|Res]) +%% end. + +no_gen(_Dir, _R) -> []. +no_order(_, _) -> true. +no_filter(X) -> X. + + + +%% Ret. Res | exit(Reason) +read(File, Order, Check) when is_function(Order), is_function(Check) -> + ?vdebug("read -> entry with~n" + " File: ~p", [File]), + Fd = open_file(File), + read_fd(File, Order, Check, Fd, 1, []). + +read_fd(File, Order, Check, Fd, StartLine, Res) -> + case do_read(Fd, "", StartLine) of + {ok, Row, EndLine} -> + ?vtrace("read_fd ->~n" + " Row: ~p~n" + " EndLine: ~p", [Row,EndLine]), + read_fd( + File, Order, Check, Fd, EndLine, + [{StartLine, Row, EndLine}|Res]); + {error, Error, EndLine} -> + ?vtrace("read_fd -> read failure:~n" + " Error: ~p~n" + " EndLine: ~p", [Error,EndLine]), + file:close(Fd), + error({failed_reading, File, StartLine, EndLine, Error}); + {eof, _EndLine} -> + Lines = + lists:sort( + fun ({_, RowA, _}, {_, RowB, _}) -> + Order(RowA, RowB) + end, + lists:reverse(Res)), + read_check(File, Check, Lines, undefined, []) end. +read_check(_, _, [], _, Res) -> + lists:reverse(Res); +read_check(File, Check, [{StartLine, Row, EndLine}|Lines], State, Res) -> + try Check(Row, State) of + {ok, NewState} -> + ?vtrace("read_check -> ok", []), + read_check(File, Check, Lines, NewState, [Row|Res]); + {{ok, NewRow}, NewState} -> + ?vtrace("read_check -> ok:~n" + " NewRow: ~p~n", [NewRow]), + read_check(File, Check, Lines, NewState, [NewRow|Res]) + catch + {error, Reason} -> + ?vtrace("read_check -> error:~n" + " Reason: ~p", [Reason]), + error({failed_check, File, StartLine, EndLine, Reason}); + Class:Reason -> + Error = {Class,Reason,erlang:get_stacktrace()}, + ?vtrace("read_check -> failure:~n" + " Error: ~p", [Error]), + error({failed_check, File, StartLine, EndLine, Error}) + end. + + + +%% XXX remove %% Ret. Res | exit(Reason) read(File, Check) when is_function(Check) -> @@ -155,11 +291,11 @@ loop(Fd, Res, Check, StartLine, File) -> "~n Error: ~p", [Error]), {error, {failed_check, File, StartLine, EndLine, Error}} end; - {error, EndLine, Error} -> + {error, Error, EndLine} -> ?vtrace("loop -> read failure: " "~n Error: ~p", [Error]), {error, {failed_reading, File, StartLine, EndLine, Error}}; - eof -> + {eof, _EndLine} -> {ok, Res} end. @@ -171,12 +307,8 @@ do_read(Io, Prompt, StartLine) -> {ok, Term} -> {ok, Term, EndLine}; {error, {Line, erl_parse, Error}} -> - {error, Line, {parse_error, Error}} + {error, {parse_error, Error}, Line} end; - {error,E,EndLine} -> - {error, EndLine, E}; - {eof, _EndLine} -> - eof; Other -> Other end. @@ -384,7 +516,7 @@ all_tdomains() -> check_tdomain(TDomain) -> SupportedTDomains = [ - ?snmpUDPDomain, + ?snmpUDPDomain, % Legacy ?transportDomainUdpIpv4, ?transportDomainUdpIpv6 ], @@ -416,40 +548,38 @@ mk_tdomain(BadDomain) -> %% --------- -check_taddress(X) -> - check_taddress(snmpUDPDomain, X). +%% XXX remove +%% check_taddress(X) -> +%% check_taddress(snmpUDPDomain, X). check_taddress(?snmpUDPDomain, X) -> check_taddress(transportDomainUdpIpv4, X); check_taddress(snmpUDPDomain, X) -> check_taddress(transportDomainUdpIpv4, X); - +%% check_taddress(?transportDomainUdpIpv4, X) -> check_taddress(transportDomainUdpIpv4, X); -check_taddress(transportDomainUdpIpv4, X) - when is_list(X) andalso (length(X) =:= 6) -> - case (catch all_integer(X)) of - true -> +check_taddress(transportDomainUdpIpv4, X) -> + case X of + [A0,A1,A2,A3,P0,P1] + when ?is_ipv4_addr(A0, A1, A2, A3), ?is_word(P0, P1) -> ok; - false -> + _ -> error({invalid_taddress, X}) end; -check_taddress(transportDomainUdpIpv4, X) -> - error({invalid_taddress, X}); - +%% check_taddress(?transportDomainUdpIpv6, X) -> check_taddress(transportDomainUdpIpv6, X); -check_taddress(transportDomainUdpIpv6, X) - when is_list(X) andalso (length(X) =:= 10) -> - case (catch all_integer(X)) of - true -> +check_taddress(transportDomainUdpIpv6, X) -> + case X of + [A0,A1,A2,A3,A4,A5,A6,A7,P0,P1] + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ?is_word(P0, P1) -> ok; - false -> + _ -> error({invalid_taddress, X}) end; -check_taddress(transportDomainUdpIpv6, X) -> - error({invalid_taddress, X}); - +%% check_taddress(BadDomain, _X) -> error({invalid_tdomain, BadDomain}). @@ -512,31 +642,65 @@ all_domains() -> transportDomainSctpDns ]. +check_domain(snmpUDPDomain) -> ok; +check_domain(transportDomainUdpIpv4) -> ok; +check_domain(transportDomainUdpIpv6) -> ok; check_domain(Domain) -> - SupportedDomains = - [ - snmpUDPDomain, - transportDomainUdpIpv4, - transportDomainUdpIpv6 - ], - AllDomains = all_domains(), - case lists:member(Domain, SupportedDomains) of + case lists:member(Domain, all_domains()) of true -> - ok; + error({unsupported_domain, Domain}); false -> - case lists:member(Domain, AllDomains) of - true -> - error({unsupported_domain, Domain}); - false -> - error({unknown_domain, Domain}) - end + error({unknown_domain, Domain}) end. - + %% --------- -%% The values of Ip and Port has both been checked at this +%% The values of Domain, Ip and Port has both been checked at this %% point, so we dont need to do that again. + +mk_taddress(snmpUDPDomain, Address) -> + mk_taddress(transportDomainUdpIpv4, Address); +mk_taddress(transportDomainUdpIpv4, {Ip, Port}) when is_list(Ip) -> + Ip ++ mk_bytes(Port); +mk_taddress(transportDomainUdpIpv4, {Ip, Port}) when is_tuple(Ip) -> + tuple_to_list(Ip) ++ mk_bytes(Port); +mk_taddress(transportDomainUdpIpv4, IpPort) when is_list(IpPort) -> + IpPort; % Should be length 6 +mk_taddress(transportDomainUdpIpv6, {Ip, Port}) when is_list(Ip) -> + Ip ++ mk_bytes(Port); +mk_taddress(transportDomainUdpIpv6, {Ip, Port}) when is_tuple(Ip) -> + tuple_to_list(Ip) ++ mk_bytes(Port); +mk_taddress(transportDomainUdpIpv6, IpPort) when is_list(IpPort) -> + case IpPort of + [A0,A1,A2,A3,A4,A5,A6,A7,P] -> + [A0,A1,A2,A3,A4,A5,A6,A7] ++ mk_bytes(P); + [A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,P0,P1] -> + [mk_word(A0, A1),mk_word(A2, A3), + mk_word(A4, A5),mk_word(A6, A7), + mk_word(A8, A9),mk_word(A10, A11), + mk_word(A12, A13),mk_word(A14, A15),P0,P1]; + _ -> + IpPort % Should already be 8 words and 2 bytes hence length 10 + end; +mk_taddress(Domain, Address) when is_atom(Domain) -> + erlang:error(badarg, [Domain,Address]); +%% +%% These are just for convenience +mk_taddress(?snmpUDPDomain, Address) -> + mk_taddress(snmpUDPDomain, Address); +mk_taddress(?transportDomainUdpIpv4, Address) -> + mk_taddress(transportDomainUdpIpv4, Address); +mk_taddress(?transportDomainUdpIpv6, Address) -> + mk_taddress(transportDomainUdpIpv6, Address); +%% Bad domain +mk_taddress(BadDomain, _) -> + error({bad_domain, BadDomain}). + + + +%% XXX remove + mk_taddress(snmpUDPDomain, Ip, Port) -> mk_taddress(transportDomainUdpIpv4, Ip, Port); mk_taddress(transportDomainUdpIpv4, Ip, Port) when is_list(Ip) -> @@ -547,7 +711,7 @@ mk_taddress(transportDomainUdpIpv6, Ip, Port) when is_list(Ip) -> Ip ++ [Port div 256, Port rem 256]; mk_taddress(transportDomainUdpIpv6 = Domain, Ip, Port) when is_tuple(Ip) -> mk_taddress(Domain, tuple_to_list(Ip), Port); - +%% %% These are just for convenience mk_taddress(?snmpUDPDomain, Ip, Port) -> mk_taddress(snmpUDPDomain, Ip, Port); @@ -555,7 +719,7 @@ mk_taddress(?transportDomainUdpIpv4, Ip, Port) -> mk_taddress(transportDomainUdpIpv4, Ip, Port); mk_taddress(?transportDomainUdpIpv6, Ip, Port) -> mk_taddress(transportDomainUdpIpv6, Ip, Port); - +%% %% Bad domain mk_taddress(BadDomain, _Ip, _Port) -> error({bad_domain, BadDomain}). @@ -563,47 +727,113 @@ mk_taddress(BadDomain, _Ip, _Port) -> %% --------- -which_domain(Ip) when is_list(Ip) andalso (length(Ip) =:= 4) -> +%% XXX remove + +which_domain([A0,A1,A2,A3]) when ?is_ipv4_addr(A0, A1, A2, A3) -> transportDomainUdpIpv4; -which_domain(Ip) when is_tuple(Ip) andalso (size(Ip) =:= 4) -> +which_domain({A0,A1,A2,A3}) when ?is_ipv4_addr(A0, A1, A2, A3) -> transportDomainUdpIpv4; -which_domain(Ip) when is_list(Ip) andalso (length(Ip) =:= 8) -> +which_domain([A0,A1,A2,A3,A4,A5,A6,A7]) + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7) -> transportDomainUdpIpv6; -which_domain(Ip) when is_tuple(Ip) andalso (size(Ip) =:= 8) -> +which_domain({A0, A1, A2, A3, A4, A5, A6, A7}) + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7) -> transportDomainUdpIpv6. %% --------- +%% XXX remove + check_ip(X) -> check_ip(snmpUDPDomain, X). check_ip(snmpUDPDomain, X) -> check_ip(transportDomainUdpIpv4, X); -check_ip(transportDomainUdpIpv4, X) when is_list(X) andalso (length(X) =:= 4) -> - case (catch all_integer(X)) of - true -> +check_ip(transportDomainUdpIpv4, X) -> + case X of + [A,B,C,D] when ?is_ipv4_addr(A, B, C, D) -> ok; - false -> + _ -> error({invalid_ip_address, X}) end; -check_ip(transportDomainUdpIpv4, X) -> - error({invalid_ip_address, X}); - -check_ip(transportDomainUdpIpv6, X) when is_list(X) andalso (length(X) =:= 8) -> - case (catch all_integer(X)) of - true -> +check_ip(transportDomainUdpIpv6, X) -> + case X of + [A,B,C,D,E,F,G,H] + when ?is_ipv6_addr(A, B, C, D, E, F, G, H) -> ok; - false -> + [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P] + when ?is_ipv6_addr( + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) -> + ok; + _ -> error({invalid_ip_address, X}) end; -check_ip(transportDomainUdpIpv6, X) -> - error({invalid_ip_address, X}); - +%% check_ip(BadDomain, _X) -> error({invalid_domain, BadDomain}). +%% --------- + +%% Check a configuration term field from a file to see if it +%% can be fed to mk_taddress/2. + +check_address(Domain, Address) + when Domain =:= snmpUDPDomain; + Domain =:= transportDomainUdpIpv4 -> + case Address of + %% Erlang native format + {{A0, A1, A2, A3}, P} + when ?is_ipv4_addr(A0, A1, A2, A3), ?is_word(P) -> + ok; + %% Erlangish format + {[A0,A1,A2,A3], P} + when ?is_ipv4_addr(A0, A1, A2, A3), ?is_word(P) -> + ok; + %% SNMP standards format + [A0,A1,A2,A3,P0,P1] + when ?is_ipv4_addr(A0, A1, A2, A3), ?is_word(P0, P1) -> + ok; + _ -> + error({invalid_address, {Domain, Address}}) + end; +check_address(transportDomainUdpIpv6 = Domain, Address) -> + case Address of + %% Erlang native format + {{A0, A1, A2, A3, A4, A5, A6, A7}, P} + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ?is_word(P) -> + ok; + %% Erlangish format + {[A0,A1,A2,A3,A4,A5,A6,A7], P} + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ?is_word(P) -> + ok; + %% Erlang friendly list format + [A0,A1,A2,A3,A4,A5,A6,A7,P] + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ?is_word(P) -> + ok; + %% Strange hybrid format with port as bytes + [A0,A1,A2,A3,A4,A5,A6,A7,P0,P1] + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7), + ?is_word(P0, P1) -> + ok; + %% SNMP standards format + [A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,P0,P1] + when ?is_ipv6_addr( + A0, A1, A2, A3, A4, A5, A6, A7, + A8, A9, A10, A11, A12, A13, A14, A15), + ?is_word(P0, P1) -> + ok; + _ -> + error({invalid_address, {Domain, Address}}) + end; +check_address(BadDomain, _) -> + error({invalid_domain, BadDomain}). + + %% --------- diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl index a222f842e5..ec6b2ac7e4 100644 --- a/lib/snmp/src/misc/snmp_config.erl +++ b/lib/snmp/src/misc/snmp_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -26,7 +26,8 @@ -compile({no_auto_import,[error/1]}). -export([config/0]). --export([write_config_file/4, append_config_file/4, read_config_file/3]). +-export([write_config_file/4, append_config_file/4, + read_config_file/3, read_config_file/4]). -export([write_agent_snmp_files/7, write_agent_snmp_files/12, @@ -2471,7 +2472,9 @@ append_config_file(Dir, FileName, Verify, Write) throw:Error -> Error; T:E -> - {error, {failed_append, Dir, FileName, T, E}} + {error, + {failed_append, Dir, FileName, + {T, E, erlang:get_stacktrace()}}} end. do_append_config_file(Dir, FileName, Verify, Write) -> @@ -2500,59 +2503,131 @@ file_write_and_close(Write, Fd, Dir, FileName) -> end. +%% XXX remove +read_config_file(Dir, FileName, Verify) -> + read_config_file( + Dir, FileName, fun snmp_conf:no_order/2, + fun (Term, State) -> + {Verify(Term), State} + end). + -spec read_config_file(Dir :: string(), - FileName :: string(), - Verify :: verify_config_entry_function()) -> + FileName :: string(), + Order :: function(), + Verify :: function()) -> {ok, Config :: list()} | {error, Reason :: term()}. -read_config_file(Dir, FileName, Verify) - when is_list(Dir) andalso is_list(FileName) andalso is_function(Verify) -> - (catch do_read_config_file(Dir, FileName, Verify)). - -do_read_config_file(Dir, FileName, Verify) -> +read_config_file(Dir, FileName, Order, Check) + when is_list(Dir), is_list(FileName), + is_function(Order), is_function(Check) -> case file:open(filename:join(Dir, FileName), [read]) of {ok, Fd} -> - Result = read_loop(Fd, [], Verify, 1), - file:close(Fd), - Result; + try + {ok, + verify_lines( + lists:sort( + fun ({_, T1, _}, {_, T2, _}) -> + Order(T1, T2) + end, + read_lines(Fd, [], 1)), + Check, undefined, [])} + catch + Error -> + {error, Error} + after + file:close(Fd) + end; {error, Reason} -> {error, {Reason, FileName}} end. -read_loop(Fd, Acc, Check, StartLine) -> - case read_term(Fd, StartLine) of +read_lines(Fd, Acc, StartLine) -> + case read_and_parse_term(Fd, StartLine) of {ok, Term, EndLine} -> - case (catch Check(Term)) of - ok -> - read_loop(Fd, [Term | Acc], Check, EndLine); - {error, Reason} -> - {error, {failed_check, StartLine, EndLine, Reason}}; - Error -> - {error, {failed_check, StartLine, EndLine, Error}} - end; - {error, EndLine, Error} -> - {error, {failed_reading, StartLine, EndLine, Error}}; - eof -> - {ok, lists:reverse(Acc)} + read_lines(Fd, [{StartLine, Term, EndLine}|Acc], EndLine); + {error, Error, EndLine} -> + throw({failed_reading, StartLine, EndLine, Error}); + {eof, _EndLine} -> + lists:reverse(Acc) end. - -read_term(Fd, StartLine) -> + +read_and_parse_term(Fd, StartLine) -> case io:request(Fd, {get_until, "", erl_scan, tokens, [StartLine]}) of {ok, Tokens, EndLine} -> case erl_parse:parse_term(Tokens) of {ok, Term} -> {ok, Term, EndLine}; {error, {Line, erl_parse, Error}} -> - {error, Line, {parse_error, Error}} + {error, {parse_error, Error}, Line} end; - {error, E, EndLine} -> - {error, EndLine, E}; - {eof, _EndLine} -> - eof; Other -> Other end. +verify_lines([], _, Acc, _) -> + list:reverse(Acc); +verify_lines( + [{StartLine, Term, EndLine}|Lines], State, Acc, Check) -> + try Check(Term, State) of + {ok, NewState} -> + verify_lines(Lines, NewState, [Term|Acc], Check); + {{ok, NewTerm}, NewState} -> + verify_lines(Lines, NewState, [NewTerm|Acc], Check) + catch + {error, Reason} -> + throw({failed_check, StartLine, EndLine, Reason}); + C:R -> + S = erlang:get_stacktrace(), + throw({failed_check, StartLine, EndLine, {C, R, S}}) + end. + + +%% XXX remove + +%% do_read_config_file(Dir, FileName, Verify) -> +%% case file:open(filename:join(Dir, FileName), [read]) of +%% {ok, Fd} -> +%% Result = read_loop(Fd, [], Verify, 1), +%% file:close(Fd), +%% Result; +%% {error, Reason} -> +%% {error, {Reason, FileName}} +%% end. + +%% read_loop(Fd, Acc, Check, StartLine) -> +%% case read_term(Fd, StartLine) of +%% {ok, Term, EndLine} -> +%% case (catch Check(Term)) of +%% ok -> +%% read_loop(Fd, [Term | Acc], Check, EndLine); +%% {error, Reason} -> +%% {error, {failed_check, StartLine, EndLine, Reason}}; +%% Error -> +%% {error, {failed_check, StartLine, EndLine, Error}} +%% end; +%% {error, EndLine, Error} -> +%% {error, {failed_reading, StartLine, EndLine, Error}}; +%% eof -> +%% {ok, lists:reverse(Acc)} +%% end. + +%% read_term(Fd, StartLine) -> +%% case io:request(Fd, {get_until, "", erl_scan, tokens, [StartLine]}) of +%% {ok, Tokens, EndLine} -> +%% case erl_parse:parse_term(Tokens) of +%% {ok, Term} -> +%% {ok, Term, EndLine}; +%% {error, {Line, erl_parse, Error}} -> +%% {error, Line, {parse_error, Error}} +%% end; +%% {error, E, EndLine} -> +%% {error, EndLine, E}; +%% {eof, _EndLine} -> +%% eof; +%% Other -> +%% Other +%% end. + agent_snmp_mk_secret(Alg, Passwd, EngineID) -> snmp_usm:passwd2localized_key(Alg, Passwd, EngineID). diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl index d7109253f7..bfedd7558c 100644 --- a/lib/snmp/test/snmp_agent_test_lib.erl +++ b/lib/snmp/test/snmp_agent_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. 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 @@ -1375,9 +1375,9 @@ config(Vsns, MgrDir, AgentConfDir, MIp, AIp) -> "~n MIp: ~p" "~n AIp: ~p", [Vsns, MgrDir, AgentConfDir, MIp, AIp]), - ?line snmp_config:write_agent_snmp_files(AgentConfDir, Vsns, - MIp, ?TRAP_UDP, AIp, 4000, - "test"), + ?line ok = + snmp_config:write_agent_snmp_files( + AgentConfDir, Vsns, MIp, ?TRAP_UDP, AIp, 4000, "test"), ?line case update_usm(Vsns, AgentConfDir) of true -> ?line copy_file(join(AgentConfDir, "usm.conf"), @@ -1486,7 +1486,7 @@ rewrite_usm_mgr(Dir, ShaKey, DesKey) -> {"mgrEngine", "newUser", "newUser", zeroDotZero, usmHMACSHAAuthProtocol, "", "", usmDESPrivProtocol, "", "", "", ShaKey, DesKey}], - ok = snmp_config:write_agent_usm_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_usm_config(Dir, "", Conf). reset_usm_mgr(Dir) -> ?line ok = file:rename(join(Dir,"usm.old"), @@ -1512,13 +1512,15 @@ update_vacm(_Vsn, Dir) -> write_community_conf(Dir, Conf) -> - snmp_config:write_agent_community_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_community_config(Dir, "", Conf). write_target_addr_conf(Dir, Conf) -> - snmp_config:write_agent_target_addr_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_target_addr_config(Dir, "", Conf). write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> - snmp_config:write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP, Vsns). + ?line ok = + snmp_config:write_agent_snmp_target_addr_conf( + Dir, ManagerIp, UDP, Vsns). rewrite_target_addr_conf(Dir, NewPort) -> ?DBG("rewrite_target_addr_conf -> entry with" @@ -1571,14 +1573,14 @@ write_target_params_conf(Dir, Vsns) -> (v3) -> {"target_v3", v3, usm, "all-rights", noAuthNoPriv} end, Conf = [F(Vsn) || Vsn <- Vsns], - snmp_config:write_agent_target_params_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_target_params_config(Dir, "", Conf). rewrite_target_params_conf(Dir, SecName, SecLevel) when is_list(SecName) andalso is_atom(SecLevel) -> ?line ok = file:rename(join(Dir,"target_params.conf"), join(Dir,"target_params.old")), Conf = [{"target_v3", v3, usm, SecName, SecLevel}], - snmp_config:write_agent_target_params_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_target_params_config(Dir, "", Conf). reset_target_params_conf(Dir) -> ?line ok = file:rename(join(Dir,"target_params.old"), @@ -1587,12 +1589,12 @@ reset_target_params_conf(Dir) -> write_notify_conf(Dir) -> Conf = [{"standard trap", "std_trap", trap}, {"standard inform", "std_inform", inform}], - snmp_config:write_agent_notify_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_notify_config(Dir, "", Conf). write_view_conf(Dir) -> Conf = [{2, [1,3,6], included, null}, {2, ?tDescr_instance, excluded, null}], - snmp_config:write_agent_view_config(Dir, "", Conf). + ?line ok = snmp_config:write_agent_view_config(Dir, "", Conf). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -- cgit v1.2.3