From 7bc7e5821ea0614ca82467bf0349f82b61d89971 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Fri, 11 Apr 2014 16:14:00 +0200 Subject: wip --- lib/snmp/src/agent/snmp_framework_mib.erl | 9 +- lib/snmp/src/agent/snmp_target_mib.erl | 22 +- lib/snmp/src/agent/snmpa_conf.erl | 2 +- lib/snmp/src/agent/snmpa_mpd.erl | 16 +- lib/snmp/src/manager/snmpm_config.erl | 642 ++++++++++++++---------------- lib/snmp/src/manager/snmpm_mpd.erl | 69 ++-- lib/snmp/src/misc/snmp_conf.erl | 381 ++++++++++-------- 7 files changed, 560 insertions(+), 581 deletions(-) diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl index 84f39df228..51f8c46d19 100644 --- a/lib/snmp/src/agent/snmp_framework_mib.erl +++ b/lib/snmp/src/agent/snmp_framework_mib.erl @@ -197,12 +197,7 @@ check_context(Context) -> %% {Name, Value}. %%----------------------------------------------------------------- check_agent({intAgentTransportDomain, D}, Domain) -> - case Domain of - undefined -> - {snmp_conf:check_domain(D), D}; - _ -> - error({invalid_agent_attribute, D}) - end; + {snmp_conf:check_domain(D), D}; check_agent({intAgentTransportAddress, Address}, Domain) -> {snmp_conf:check_address(Domain, Address), Domain}; check_agent(Entry, Domain) -> @@ -224,7 +219,7 @@ check_agent(X) -> %% Ordering function to sort intAgentTransportDomain first %% hence before intAgentTransportAddress -order_agent({intAgentTransportDomain, _}, {intAgentTransportDomain, _}) -> +order_agent({Name, _}, {Name, _}) -> true; %% Less than or equal order_agent(_, {intAgentTransportDomain, _}) -> false; %% Greater than diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl index 6dd3b6e23a..cff1e253c3 100644 --- a/lib/snmp/src/agent/snmp_target_mib.erl +++ b/lib/snmp/src/agent/snmp_target_mib.erl @@ -263,16 +263,16 @@ check_target_addr( TagList, Params, EngineId, Mask, MMS]), snmp_conf:check_string(Name,{gt,0}), snmp_conf:check_domain(Domain), - snmp_conf:check_address(Domain, Address), + NAddress = 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), - check_mask(Domain, Mask), + NMask = check_mask(Domain, Mask), TDomain = snmp_conf:mk_tdomain(Domain), - TAddress = snmp_conf:mk_taddress(Domain, Address), - TMask = snmp_conf:mk_taddress(Domain, Mask), + TAddress = snmp_conf:mk_taddress(Domain, NAddress), + TMask = snmp_conf:mk_taddress(Domain, NMask), snmp_conf:check_packet_size(MMS), ?vtrace("check target address done",[]), Addr = {Name, TDomain, TAddress, Timeout, @@ -286,13 +286,21 @@ check_engine_id(discovery) -> check_engine_id(EngineId) -> snmp_conf:check_string(EngineId). +check_address(Domain, Address) -> + case snmp_conf:check_address(Domain, Address) of + ok -> + Address; + {ok, FixedAddress} -> + FixedAddress + end. + check_mask(_Domain, []) -> - ok; + []; check_mask(Domain, Mask) -> - try snmp_conf:check_address(Domain, Mask) + try check_address(Domain, Mask) catch {error, {invalid_address, Info}} -> - {error, {invalid_mask, Info}} + error({invalid_mask, Info}) end. %%----------------------------------------------------------------- diff --git a/lib/snmp/src/agent/snmpa_conf.erl b/lib/snmp/src/agent/snmpa_conf.erl index a405987c8a..f055f89880 100644 --- a/lib/snmp/src/agent/snmpa_conf.erl +++ b/lib/snmp/src/agent/snmpa_conf.erl @@ -140,7 +140,7 @@ verify_agent_conf(X, _) -> error({bad_agent_config, X}). check_agent_conf_entry(Entry, State) -> - {ok, _NewState} = snmp_framework_mib:check_agent(Entry, State). + snmp_framework_mib:check_agent(Entry, State). write_agent_conf(Fd, "", Conf) -> write_agent_conf(Fd, Conf); diff --git a/lib/snmp/src/agent/snmpa_mpd.erl b/lib/snmp/src/agent/snmpa_mpd.erl index 9bb4556788..2db98d9fc2 100644 --- a/lib/snmp/src/agent/snmpa_mpd.erl +++ b/lib/snmp/src/agent/snmpa_mpd.erl @@ -186,12 +186,12 @@ discarded_pdu(Variable) -> inc(Variable). 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 -> + try snmp_conf:mk_tdomain(Domain) of + TDomain -> + try snmp_conf:mk_taddress(Domain, Address) of + TAddress -> v1_v2c_proc_dec( - Vsn, NoteStore, Community, Domain, Address, + Vsn, NoteStore, Community, TDomain, TAddress, LocalEngineID, Data, HS, Log, Packet) catch _ -> @@ -203,10 +203,8 @@ v1_v2c_proc( end. v1_v2c_proc_dec( - Vsn, NoteStore, Community, Domain, Address, + Vsn, NoteStore, Community, TDomain, TAddress, LocalEngineID, Data, HS, Log, Packet) -> - TDomain = snmp_conf:mk_tdomain(Domain), - 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 @@ -233,7 +231,7 @@ v1_v2c_proc_dec( case Pdu#pdu.type of 'set-request' -> %% Check if this message has already been processed - Key = {agent, {Domain, Address}, ReqId}, + Key = {agent, {TDomain, TAddress}, ReqId}, case snmp_note_store:get_note(NoteStore, Key) of undefined -> %% Set the processed note _after_ pdu processing. diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 43d394e9d9..af2262d988 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -335,27 +335,17 @@ register_agent(UserId, TargetName, Config0) %% is not present %% 3) Check that there are no invalid or erroneous configs %% 4) Check that the manager is capable of using the selected version - case verify_agent_config(Config0) of - {ok, Config} -> - call({register_agent, UserId, TargetName, Config}); - Error -> - Error - end. - - -verify_agent_config(Conf0) -> try - begin - verify_mandatory(Conf0, [engine_id, address, reg_type]), - verify_invalid(Conf0, [user_id]), - Conf = verify_agent_config3(Conf0), - Vsns = versions(), - Vsn = which_version(Conf), - verify_version(Vsn, Vsns), - {ok, Conf} - end + verify_mandatory(Config0, [engine_id, reg_type]), + verify_oneof(Config0, [address, taddress]), + verify_invalid(Config0, [user_id]), + Config = verify_agent(Config0), + Vsns = versions(), + Vsn = which_version(Config), + verify_version(Vsn, Vsns), + call({register_agent, UserId, TargetName, Config}) catch - throw:Error -> + Error -> Error end. @@ -381,37 +371,9 @@ verify_version(Vsn, Vsns) -> ok; false -> Reason = {version_not_supported_by_manager, Vsn, Vsns}, - throw({error, Reason}) - end. - -verify_agent_config3(Conf0) -> - %% Fix (transport) address and domain - {TDomain, Conf1} = - case lists:keysearch(tdomain, 1, Conf0) of - {value, {tdomain, Dom}} -> - {Dom, Conf0}; - false -> - Dom = default_transport_domain(), - {Dom, [{tdomain, Dom} | Conf0]} - end, - Conf2 = case lists:keysearch(address, 1, Conf1) of - {value, {address, Address}} -> - lists:keyreplace(address, 1, Conf1, - {address, {TDomain, Address}}); - false -> - %% This is a mandatory config option, - %% a later test will detect this - Conf1 - end, - case verify_agent2(Conf2) of - {ok, Conf} -> - Conf; - {error, _} = ERROR -> - throw(ERROR) + error(Reason) end. -verify_agent_config2(Conf) -> - verify_agent2(Conf). unregister_agent(UserId, TargetName) -> @@ -444,7 +406,7 @@ agent_info(TargetName, Item) -> [] -> {error, not_found} end. - + agent_info(Addr0, Port, Item) -> Addr = normalize_address(Addr0), do_agent_info(Addr, Port, Item). @@ -474,38 +436,6 @@ which_agents(UserId) -> [TargetName || [TargetName] <- Agents]. -verify_agent_info(TargetName, Info0) -> - try - begin - verify_invalid(Info0, [user_id]), - %% Check if address is part of the list and - %% if so update it with the domain info. - Info = - case lists:keysearch(address, 1, Info0) of - {value, {address, Addr}} -> - %% If domain is part of the info, then use it. - %% If not, lookup what is already stored for - %% this agent and use that. - Domain = - case lists:keysearch(tdomain, 1, Info0) of - {value, {tdomain, Dom}} -> - Dom; - false -> - {ok, Dom} = - agent_info(TargetName, tdomain), - Dom - end, - Addr2 = {Domain, Addr}, - lists:keyreplace(address, 1, Info0, {address, Addr2}); - false -> - Info0 - end, - verify_agent2(Info) - end - catch - throw:Error -> - Error - end. update_agent_info(UserId, TargetName, Info) -> call({update_agent_info, UserId, TargetName, Info}). @@ -1666,8 +1596,8 @@ init_agent_default(Item, Val) when Item =/= user_id -> read_agents_config_file(Dir) -> - Check = fun(C, S) -> {check_agent_config2(C), S} end, - case read_file(Dir, "agents.conf", Check, []) of + Verify = fun check_agent_config2/1, + case read_file(Dir, "agents.conf", Verify, []) of {ok, Conf} -> Conf; Error -> @@ -1691,119 +1621,44 @@ check_agent_config2(Agent) -> end. %% For backward compatibility -check_agent_config({UserId, - TargetName, - Community, - Ip, Port, - EngineId, - Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel}) -> +check_agent_config( + {UserId, TargetName, Community, Ip, Port, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel}) -> TDomain = default_transport_domain(), - check_agent_config({UserId, - TargetName, - Community, - TDomain, Ip, Port, - EngineId, - Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel}); - -check_agent_config({UserId, - TargetName, - Community, - TDomain, Ip, Port, - EngineId, - Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel}) -> - ?vtrace("check_agent_config -> entry with" - "~n UserId: ~p" - "~n TargetName: ~p" - "~n Community: ~p" - "~n TDomain: ~p" - "~n Ip: ~p" - "~n Port: ~p" - "~n EngineId: ~p" - "~n Timeout: ~p" - "~n MaxMessageSize: ~p" - "~n Version: ~p" - "~n SecModel: ~p" - "~n SecName: ~p" - "~n SecLevel: ~p", - [UserId, TargetName, Community, - TDomain, Ip, Port, - EngineId, Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel]), - Addr = normalize_address(TDomain, Ip), - ?vtrace("check_agent_config -> Addr: ~p", [Addr]), - Agent = {UserId, - TargetName, - Community, - TDomain, Addr, Port, - EngineId, - Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel}, - {ok, verify_agent(Agent)}; + check_agent_config( + UserId, TargetName, Community, TDomain, {Ip, Port}, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel); +check_agent_config( + {UserId, TargetName, Community, TDomain, Ip, Port, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel}) -> + check_agent_config( + UserId, TargetName, Community, TDomain, {Ip, Port}, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel); check_agent_config(Agent) -> error({bad_agent_config, Agent}). - -init_agents_config([]) -> - ok; -init_agents_config([Agent|Agents]) -> - init_agent_config(Agent), - init_agents_config(Agents). - -init_agent_config({_UserId, ?DEFAULT_TARGETNAME = TargetName, _Config}) -> - throw({error, {invalid_target_name, TargetName}}); -init_agent_config({UserId, TargetName, Config}) -> - case handle_register_agent(UserId, TargetName, Config) of - ok -> - ok; - Error -> - throw(Error) - end. - - -%% For backward compatibility -verify_agent({UserId, - TargetName, - Comm, - Ip, Port, - EngineId, - Timeout, MMS, - Version, SecModel, SecName, SecLevel}) -> - TDomain = default_transport_domain(), - verify_agent({UserId, - TargetName, - Comm, - TDomain, Ip, Port, - EngineId, - Timeout, MMS, - Version, SecModel, SecName, SecLevel}); - -verify_agent({UserId, - TargetName, - Comm, - TDomain, Ip, Port, - EngineId, - Timeout, MMS, - Version, SecModel, SecName, SecLevel}) -> - ?vdebug("verify_agent -> entry with" +check_agent_config( + UserId, TargetName, Comm, TDomain, TAddress, + EngineId, Timeout, MMS, + Version, SecModel, SecName, SecLevel) -> + ?vdebug("check_agent_config -> entry with" "~n UserId: ~p" "~n TargetName: ~p", [UserId, TargetName]), snmp_conf:check_string(TargetName, {gt, 0}), - snmp_conf:check_integer(Port, {gt, 0}), %% Note that the order of Conf *is* important. %% Some properties may depend on others, so that %% in order to verify one property, another must %% be already verified (and present). An example - %% of this is the property 'address', for which + %% of this is the property 'taddress', for which %% the property tdomain is needed. - Conf0 = + Conf = [{reg_type, target_name}, {tdomain, TDomain}, - %% This should be taddress, but what the*... - {address, {TDomain, Ip}}, - {port, Port}, + {taddress, TAddress}, {community, Comm}, {engine_id, EngineId}, {timeout, Timeout}, @@ -1813,32 +1668,148 @@ verify_agent({UserId, {sec_name, SecName}, {sec_level, SecLevel} ], - case verify_agent2(Conf0) of - {ok, Conf} -> - {UserId, TargetName, Conf, Version}; - Err -> - throw(Err) + {ok, {UserId, TargetName, verify_agent(Conf), Version}}. + + + +init_agents_config([]) -> + ok; +init_agents_config([Agent|Agents]) -> + init_agent_config(Agent), + init_agents_config(Agents). + +init_agent_config({_UserId, ?DEFAULT_TARGETNAME = TargetName, _Config}) -> + error({invalid_target_name, TargetName}); +init_agent_config({UserId, TargetName, Config}) -> + case handle_register_agent(UserId, TargetName, Config) of + ok -> + ok; + Error -> + throw(Error) end. -verify_agent2(Conf) -> - verify_agent2(Conf, []). -verify_agent2([], VerifiedConf) -> - {ok, VerifiedConf}; -verify_agent2([{Item, Val0}|Items], VerifiedConf) -> - case verify_val(Item, Val0) of - {ok, Val} -> - verify_agent2(Items, [{Item, Val} | VerifiedConf]); - Err -> - Err + +%% Sort tdomain first +order_agent({Item, _}, {Item, _}) -> + true; %% Less than or equal +order_agent(_, {tdomain, _}) -> + false; %% Greater than +order_agent(_, _) -> + true. %% Less than or equal + +verify_agent(Conf) -> + verify_agent(lists:sort(fun order_agent/2, Conf), []). + +verify_agent([], VerifiedConf) -> + list:reverse(VerifiedConf); +verify_agent([{_Item, _} = Entry|Conf], VerifiedConf) -> +%% verify_invalid(VerifiedConf, [_Item]), % Check for duplicate + verify_agent(Conf, VerifiedConf, Entry); +verify_agent([Bad|_], _VerifiedConf) -> + error({bad_agent_config, Bad}). + +verify_agent(Conf, VerifiedConf, {taddress = Item, TAddress} = Entry) -> + verify_invalid(VerifiedConf, [address,port]), + {TDomain, VC} = + case lists:keysearch(tdomain, 1, VerifiedConf) of + {value, {tdomain,TD}} -> + {TD, VerifiedConf}; + _ -> + %% Insert tdomain since it is missing + TD = default_transport_domain(), + {TD, [{tdomain, TD}|VerifiedConf]} + end, + case snmp_conf:check_address(TDomain, TAddress) of + ok -> + verify_agent(Conf, [Entry|VC]); + {ok, NAddress} -> + verify_agent(Conf, [{Item, NAddress}|VC]) + end; +verify_agent(Conf, VerifiedConf, {address = Item, Address} = Entry) -> + verify_invalid(VerifiedConf, [taddress]), + {TDomain, VC} = + case lists:keysearch(tdomain, 1, VerifiedConf) of + {value, {tdomain,TD}} -> + {TD, VerifiedConf}; + _ -> + %% Insert tdomain since it is missing + TD = default_transport_domain(), + {TD, [{tdomain, TD}|VerifiedConf]} + end, + FakePort = make_ref(), + case snmp_conf:check_address(TDomain, Address, FakePort) of + ok -> + verify_agent(Conf, [Entry|VC]); + {ok, {NAddress,FakePort}} -> + verify_agent(Conf, [{Item, NAddress}|VC]); + {ok, _} -> + error({invalid_address, {TDomain, Address}}) + end; +verify_agent(Conf, VerifiedConf, {port, Port} = Entry) -> + verify_invalid(VerifiedConf, [taddress]), + ok = snmp_conf:check_address(snmpUDPDomain, {{0, 0, 0, 0}, Port}), + verify_agent(Conf, [Entry|VerifiedConf]); +verify_agent(Conf, VerifiedConf, {Item, Val} = Entry) -> + case verify_agent_entry(Item, Val) of + ok -> + verify_agent(Conf, [Entry|VerifiedConf]); + {ok, NewVal} -> + verify_agent(Conf, [{Item, NewVal}|VerifiedConf]) + end. + +verify_agent_entry(user_id, _UserId) -> + ok; +verify_agent_entry(reg_type, RegType) -> + if + RegType =:= addr_port; + RegType =:= target_name -> + ok; + true -> + error({bad_reg_type, RegType}) + end; +verify_agent_entry(tdomain, TDomain) -> + snmp_conf:check_domain(TDomain); +verify_agent_entry(community, Comm) -> + snmp_conf:check_string(Comm); +verify_agent_entry(engine_id, EngineId) -> + case EngineId of + discovery -> + ok; + _ -> + snmp_conf:check_string(EngineId) + end; +verify_agent_entry(timeout, Timeout) -> + snmp_conf:check_timer(Timeout); +verify_agent_entry(max_message_size, MMS) -> + snmp_conf:check_packet_size(MMS); +verify_agent_entry(version, V) -> + if + V =:= v1; + V =:= v2; + V =:= v3 -> + ok; + true -> + error({bad_version, V}) end; -verify_agent2([Bad|_], _VerifiedConf) -> - {error, {bad_agent_config, Bad}}. +verify_agent_entry(sec_model, Model) -> + snmp_conf:check_sec_model(Model); +verify_agent_entry(sec_name, Name) -> + try snmp_conf:check_string(Name) + catch + _ -> + error({bad_sec_name, Name}) + end; +verify_agent_entry(sec_level, Level) -> + snmp_conf:check_sec_level(Level); +verify_agent_entry(Item, _) -> + error({unknown_item, Item}). + read_users_config_file(Dir) -> - Check = fun(C, S) -> {check_user_config(C), S} end, - case read_file(Dir, "users.conf", Check, []) of + Verify = fun check_user_config/1, + case read_file(Dir, "users.conf", Verify, []) of {ok, Conf} -> Conf; Error -> @@ -1864,15 +1835,12 @@ check_user_config({Id, Mod, Data, DefaultAgentConfig} = _User) case (catch verify_user_behaviour(Mod)) of ok -> ?vtrace("check_user_config -> user behaviour verified", []), - case verify_user_agent_config(DefaultAgentConfig) of - {ok, DefAgentConf} -> - ?vtrace("check_user_config -> " - "user agent (default) config verified", []), - User2 = {Id, Mod, Data, DefAgentConf}, - {ok, User2}; - {error, Reason} -> - error({bad_default_agent_config, Reason}) - end; + DefAgentConf = + verify_default_agent_config(DefaultAgentConfig), + ?vtrace("check_user_config -> " + "user agent (default) config verified", []), + User2 = {Id, Mod, Data, DefAgentConf}, + {ok, User2}; Error -> throw(Error) end; @@ -1904,7 +1872,7 @@ init_user_config(User) -> error_msg("user config check failed: " "~n~w~n~w", [User, Reason]) end. - + verify_user({Id, UserMod, UserData}) -> verify_user({Id, UserMod, UserData, []}); verify_user({Id, UserMod, UserData, DefaultAgentConfig}) @@ -1917,15 +1885,19 @@ verify_user({Id, UserMod, UserData, DefaultAgentConfig}) [Id, UserMod, UserData, DefaultAgentConfig]), case (catch verify_user_behaviour(UserMod)) of ok -> - case verify_user_agent_config(DefaultAgentConfig) of - {ok, DefAgentConf} -> - Config = default_agent_config(DefAgentConf), - {ok, #user{id = Id, - mod = UserMod, - data = UserData, - default_agent_config = Config}}; - {error, Reason} -> - error({bad_default_agent_config, Reason}) + try + Config = + default_agent_config( + verify_default_agent_config(DefaultAgentConfig)), + {ok, #user{id = Id, + mod = UserMod, + data = UserData, + default_agent_config = Config}} + catch + Error -> + ?vdebug("verify_user default_agent_config -> throw" + "~n Error: ~p", [Error]), + error({bad_default_agent_config, Error}) end; Error -> throw(Error) @@ -1936,22 +1908,22 @@ verify_user({Id, _UserMod, _UserData, DefaultAgentConfig}) verify_user({Id, _, _, _}) -> {error, {bad_user_id, Id}}. -verify_user_agent_config(Conf) -> +verify_default_agent_config(Conf) -> try - begin - verify_invalid(Conf, [user_id, engine_id, address]), - verify_agent_config2(Conf) - end + verify_invalid( + Conf, + [user_id, engine_id, address, tdomain, taddress]), + verify_agent(Conf) catch - throw:Error -> - ?vdebug("verify_user_agent_config -> throw" + Error -> + ?vdebug("verify_default_agent_config -> throw" "~n Error: ~p", [Error]), - Error + error({bad_default_agent_config, Error}) end. read_usm_config_file(Dir) -> - Check = fun(C, S) -> {check_usm_user_config(C), S} end, - case read_file(Dir, "usm.conf", Check, []) of + Verify = fun check_usm_user_config/1, + case read_file(Dir, "usm.conf", Verify, []) of {ok, Conf} -> Conf; Error -> @@ -2139,8 +2111,8 @@ is_crypto_supported(Func) -> read_manager_config_file(Dir) -> - Check = fun(Conf, State) -> {check_manager_config(Conf), State} end, - case read_file(Dir, "manager.conf", Check) of + Verify = fun check_manager_config/1, + case read_file(Dir, "manager.conf", Verify) of {ok, Conf} -> ?d("read_manager_config_file -> ok: " "~n Conf: ~p", [Conf]), @@ -2218,44 +2190,80 @@ ensure_manager_config(Confs, [{Key,_} = DefKeyVal|Defs]) -> -read_file(Dir, FileName, Check, Default) -> +read_file(Dir, FileName, Verify, Default) -> File = filename:join(Dir, FileName), case file:read_file_info(File) of {ok, _} -> - case (catch do_read(File, Check)) of - {ok, Conf} -> - {ok, Conf}; - Error -> - ?vtrace("read_file -> read failed:" - "~n Error: ~p", [Error]), - Error - end; - {error, Reason} -> + read_file(File, Verify); + {error, Reason} -> ?vlog("failed reading config from ~s: ~p", [FileName, Reason]), {ok, Default} end. -read_file(Dir, FileName, Check) -> +read_file(Dir, FileName, Verify) -> File = filename:join(Dir, FileName), case file:read_file_info(File) of {ok, _} -> - case (catch do_read(File, Check)) of - {ok, Conf} -> - ?vtrace("read_file -> read ok" - "~n Conf: ~p", [Conf]), - {ok, Conf}; - Error -> - ?vtrace("read_file -> read failed:" - "~n Error: ~p", [Error]), - Error - end; + read_file(File, Verify); {error, Reason} -> error_msg("failed reading config from ~s: ~p", [FileName, Reason]), {error, {failed_reading, FileName, Reason}} end. -do_read(File, Check) -> - {ok, snmp_conf:read(File, Check)}. +read_file(File, Verify) -> + Check = fun (Config, State) -> {Verify(Config), State} end, + try snmp_conf:read(File, Check) of + Conf -> + ?vtrace("read_file -> read ok" + "~n Conf: ~p", [Conf]), + {ok, Conf} + catch + Error -> + ?vtrace("read_file -> read failed:" + "~n Error: ~p", [Error]), + Error + end. + +%% XXX remove + +%% read_file(Dir, FileName, Check, Default) -> +%% File = filename:join(Dir, FileName), +%% case file:read_file_info(File) of +%% {ok, _} -> +%% case (catch do_read(File, Check)) of +%% {ok, Conf} -> +%% {ok, Conf}; +%% Error -> +%% ?vtrace("read_file -> read failed:" +%% "~n Error: ~p", [Error]), +%% Error +%% end; +%% {error, Reason} -> +%% ?vlog("failed reading config from ~s: ~p", [FileName, Reason]), +%% {ok, Default} +%% end. + +%% read_file(Dir, FileName, Check) -> +%% File = filename:join(Dir, FileName), +%% case file:read_file_info(File) of +%% {ok, _} -> +%% case (catch do_read(File, Check)) of +%% {ok, Conf} -> +%% ?vtrace("read_file -> read ok" +%% "~n Conf: ~p", [Conf]), +%% {ok, Conf}; +%% Error -> +%% ?vtrace("read_file -> read failed:" +%% "~n Error: ~p", [Error]), +%% Error +%% end; +%% {error, Reason} -> +%% error_msg("failed reading config from ~s: ~p", [FileName, Reason]), +%% {error, {failed_reading, FileName, Reason}} +%% end. + +%% do_read(File, Check) -> +%% {ok, snmp_conf:read(File, Check)}. %%-------------------------------------------------------------------- @@ -2795,13 +2803,24 @@ handle_update_agent_info(TargetName, Info0) -> "~n TargetName: ~p" "~n Info0: ~p", [TargetName, Info0]), %% Verify info - try verify_agent_info(TargetName, Info0) of - {ok, Info} -> - do_update_agent_info(TargetName, Info); - Error -> - Error + try + verify_invalid(Info0, [user_id]), + %% If domain is part of the info, then use it. + %% If not, lookup what is already stored for + %% this agent and use that. + Info = + case lists:keysearch(tdomain, 1, Info0) of + {value, {tdomain, _}} -> + Info0; + false -> + {ok, TDomain} = + agent_info(TargetName, tdomain), + [{tdomain, TDomain}|Info0] + end, + verify_agent(Info), + do_update_agent_info(TargetName, Info) catch - throw:Error -> + Error -> Error; T:E -> {error, {failed_info_verification, Info0, T, E}} @@ -2997,7 +3016,7 @@ verify_mandatory(Conf, [Mand|Mands]) -> true -> verify_mandatory(Conf, Mands); false -> - throw({error, {missing_mandatory_config, Mand}}) + error({missing_mandatory_config, Mand}) end. verify_invalid(_, []) -> @@ -3007,99 +3026,22 @@ verify_invalid(Conf, [Inv|Invs]) -> false -> verify_invalid(Conf, Invs); true -> - throw({error, {illegal_config, Inv}}) + error({illegal_config, Inv}) end. - -verify_val(user_id, UserId) -> - {ok, UserId}; -verify_val(reg_type, RegType) - when (RegType =:= addr_port) orelse (RegType =:= target_name) -> - {ok, RegType}; -verify_val(tdomain = Item, snmpUDPDomain = _Domain) -> - verify_val(Item, transportDomainUdpIpv4); -verify_val(tdomain, Domain) -> - case lists:member(Domain, ?SUPPORTED_DOMAINS) of +verify_oneof(Conf, [Mand|Mands]) -> + case lists:keymember(Mand, 1, Conf) of true -> - {ok, Domain}; + ok; false -> - case lists:member(Domain, snmp_conf:all_domains()) of - true -> - error({unsupported_domain, Domain}); - false -> - error({unknown_domain, Domain}) + case Mands of + [] -> + error({missing_mandatory_config, Mand}); + _ -> + verify_oneof(Conf, Mands) end - end; -verify_val(address, {Domain, Addr0}) -> - case normalize_address(Domain, Addr0) of - {_A1, _A2, _A3, _A4} = Addr -> - {ok, Addr}; - {_A1, _A2, _A3, _A4, _A5, _A6, _A7, _A8} = Addr -> - {ok, Addr}; - _ when is_list(Addr0) -> - case (catch snmp_conf:check_ip(Addr0)) of - ok -> - {ok, list_to_tuple(Addr0)}; - Err -> - Err - end; - _ -> - error({bad_address, Addr0}) - end; -verify_val(address, BadAddress) -> - error({bad_address, BadAddress}); -verify_val(port, Port) -> - case (catch snmp_conf:check_integer(Port, {gt, 0})) of - ok -> - {ok, Port}; - Err -> - Err - end; -verify_val(community, Comm) -> - case (catch snmp_conf:check_string(Comm)) of - ok -> - {ok, Comm}; - Err -> - Err - end; -verify_val(engine_id, discovery = EngineId) -> - {ok, EngineId}; -verify_val(engine_id, EngineId) -> - case (catch snmp_conf:check_string(EngineId)) of - ok -> - {ok, EngineId}; - Err -> - Err - end; -verify_val(timeout, Timeout) -> - (catch snmp_conf:check_timer(Timeout)); -verify_val(max_message_size, MMS) -> - case (catch snmp_conf:check_packet_size(MMS)) of - ok -> - {ok, MMS}; - Err -> - Err - end; -verify_val(version, V) - when (V =:= v1) orelse (V =:= v2) orelse (V =:= v3) -> - {ok, V}; -verify_val(version, BadVersion) -> - error({bad_version, BadVersion}); -verify_val(sec_model, Model) -> - (catch snmp_conf:check_sec_model(Model)); -verify_val(sec_name, Name) when is_list(Name) -> - case (catch snmp_conf:check_string(Name)) of - ok -> - {ok, Name}; - Err -> - Err - end; -verify_val(sec_name, BadName) -> - error({bad_sec_name, BadName}); -verify_val(sec_level, Level) -> - (catch snmp_conf:check_sec_level(Level)); -verify_val(Item, _) -> - {error, {unknown_item, Item}}. + end. + %%%------------------------------------------------------------------- diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl index 953c94ab54..fe5ed6b755 100644 --- a/lib/snmp/src/manager/snmpm_mpd.erl +++ b/lib/snmp/src/manager/snmpm_mpd.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2012. 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 @@ -93,7 +93,9 @@ reset(#state{v3 = V3}) -> %% section 4.2.1 in rfc2272) %%----------------------------------------------------------------- process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) -> + process_msg(Msg, Domain, {Addr, Port}, State, NoteStore, Logger). +process_msg(Msg, Domain, Address, State, NoteStore, Logger) -> inc(snmpInPkts), case (catch snmp_pdus:dec_message_only(binary_to_list(Msg))) of @@ -102,17 +104,17 @@ process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) -> #message{version = 'version-1', vsn_hdr = Community, data = Data} when State#state.v1 =:= true -> HS = ?empty_msg_size + length(Community), - process_v1_v2c_msg('version-1', NoteStore, Msg, - Domain, Addr, Port, - Community, Data, HS, Logger); + process_v1_v2c_msg( + 'version-1', NoteStore, Msg, Domain, Address, + Community, Data, HS, Logger); %% Version 2 #message{version = 'version-2', vsn_hdr = Community, data = Data} when State#state.v2c =:= true -> HS = ?empty_msg_size + length(Community), - process_v1_v2c_msg('version-2', NoteStore, Msg, - Domain, Addr, Port, - Community, Data, HS, Logger); + process_v1_v2c_msg( + 'version-2', NoteStore, Msg, Domain, Address, + Community, Data, HS, Logger); %% Version 3 #message{version = 'version-3', vsn_hdr = H, data = Data} @@ -122,7 +124,7 @@ process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) -> "~n msgFlags: ~p" "~n msgSecModel: ~p", [H#v3_hdr.msgID,H#v3_hdr.msgFlags,H#v3_hdr.msgSecurityModel]), - process_v3_msg(NoteStore, Msg, H, Data, Addr, Port, Logger); + process_v3_msg(NoteStore, Msg, H, Data, Address, Logger); %% Crap {'EXIT', {bad_version, Vsn}} -> @@ -148,32 +150,27 @@ process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) -> %%----------------------------------------------------------------- %% Handles a Community based message (v1 or v2c). %%----------------------------------------------------------------- -process_v1_v2c_msg(Vsn, _NoteStore, Msg, Domain, - Addr, Port, - Community, Data, HS, Log) -> +process_v1_v2c_msg( + Vsn, _NoteStore, Msg, Domain, Address, Community, Data, HS, Log) -> ?vdebug("process_v1_v2c_msg -> entry with" "~n Vsn: ~p" "~n Domain: ~p" - "~n Addr: ~p" - "~n Port: ~p" + "~n Address: ~p" "~n Community: ~p" - "~n HS: ~p", [Vsn, Domain, Addr, Port, Community, HS]), - + "~n HS: ~p", [Vsn, Domain, Address, Community, HS]), + {TDomain, TAddress} = try - begin - TD = snmp_conf:mk_tdomain(Domain), - TA = snmp_conf:mk_taddress(Domain, Addr, Port), - {TD, TA} - end + {snmp_conf:mk_tdomain(Domain), + snmp_conf:mk_taddress(Domain, Address)} catch throw:{error, TReason} -> throw({discarded, {badarg, Domain, TReason}}) end, Max = get_max_message_size(), - AgentMax = get_agent_max_message_size(Addr, Port), + AgentMax = get_agent_max_message_size(Address), PduMS = pdu_ms(Max, AgentMax, HS), ?vtrace("process_v1_v2c_msg -> PduMS: ~p", [PduMS]), @@ -213,13 +210,12 @@ sec_model('version-2') -> ?SEC_V2C. %% Handles a SNMPv3 Message, following the procedures in rfc2272, %% section 4.2 and 7.2 %%----------------------------------------------------------------- -process_v3_msg(NoteStore, Msg, Hdr, Data, Addr, Port, Log) -> +process_v3_msg(NoteStore, Msg, Hdr, Data, Address, Log) -> + ?vdebug( + "process_v3_msg -> entry with~n" + " Hdr: ~p~n" + " Address: ~p", [Hdr, Address]), - ?vdebug("process_v3_msg -> entry with" - "~n Hdr: ~p" - "~n Addr: ~p" - "~n Port: ~p", [Hdr, Addr, Port]), - %% 7.2.3 #v3_hdr{msgID = MsgID, msgMaxSize = MMS, @@ -352,8 +348,8 @@ process_v3_msg(NoteStore, Msg, Hdr, Data, Addr, Port, Log) -> %% 4.2.2.1.1 - we don't handle proxys yet => we only %% handle CtxEngineID to ourselves %% Check that we actually know of an agent with this - %% CtxEngineID and Addr/Port - case is_known_engine_id(CtxEngineID, Addr, Port) of + %% CtxEngineID and Address + case is_known_engine_id(CtxEngineID, Address) of true -> ?vtrace("and the agent EngineID (~p) " "is know to us", [CtxEngineID]), @@ -866,7 +862,7 @@ get_max_message_size() -> end. %% The the MMS of the agent -get_agent_max_message_size(Addr, Port) -> +get_agent_max_message_size({Addr, Port}) -> case snmpm_config:get_agent_engine_max_message_size(Addr, Port) of {ok, MMS} -> MMS; @@ -874,6 +870,14 @@ get_agent_max_message_size(Addr, Port) -> ?vlog("unknown agent: ~w:~w", [Addr, Port]), get_max_message_size() end. +%% get_agent_max_message_size(Addr, Port) -> +%% case snmpm_config:get_agent_engine_max_message_size(Addr, Port) of +%% {ok, MMS} -> +%% MMS; +%% _Error -> +%% ?vlog("unknown agent: ~w:~w", [Addr, Port]), +%% get_max_message_size() +%% end. %% Get "our" (manager) engine id get_engine_id() -> @@ -888,9 +892,12 @@ get_engine_id() -> get_agent_engine_id(Name) -> snmpm_config:get_agent_engine_id(Name). -is_known_engine_id(EngineID, Addr, Port) -> +is_known_engine_id(EngineID, {Addr, Port}) -> snmpm_config:is_known_engine_id(EngineID, Addr, Port). +%% is_known_engine_id(EngineID, Addr, Port) -> +%% snmpm_config:is_known_engine_id(EngineID, Addr, Port). + % get_agent_engine_id(Addr, Port) -> % case snmpm_config:get_agent_engine_id(Addr, Port) of % {ok, Id} -> diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl index c52b4bb6fb..f85f1d3828 100644 --- a/lib/snmp/src/misc/snmp_conf.erl +++ b/lib/snmp/src/misc/snmp_conf.erl @@ -45,9 +45,9 @@ mk_tdomain/1, which_domain/1, check_ip/1, check_ip/2, - check_address/2, + check_address/2, check_address/3, check_taddress/2, - mk_taddress/2, mk_taddress/3, + mk_taddress/2, check_packet_size/1, @@ -146,38 +146,8 @@ read_files(Dir, [{FileName, Gen, Order, Check, Filter}|Files], Res) 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. @@ -185,6 +155,9 @@ no_filter(X) -> X. +read(File, Check) -> + read(File, fun no_order/2, Check). + %% Ret. Res | exit(Reason) read(File, Order, Check) when is_function(Order), is_function(Check) -> ?vdebug("read -> entry with~n" @@ -240,80 +213,29 @@ read_check(File, Check, [{StartLine, Row, EndLine}|Lines], State, Res) -> error({failed_check, File, StartLine, EndLine, Error}) end. - - -%% XXX remove - -%% Ret. Res | exit(Reason) -read(File, Check) when is_function(Check) -> - ?vdebug("read -> entry with" - "~n File: ~p", [File]), - - Fd = open_file(File), - - case loop(Fd, [], Check, 1, File) of - {error, Reason} -> - file:close(Fd), - error(Reason); - {ok, Res} -> - file:close(Fd), - Res - end. - open_file(File) -> case file:open(File, [read]) of - {ok, Fd} -> - Fd; - {error, Reason} -> - error({failed_open, File, Reason}) - end. - -loop(Fd, Res, Check, StartLine, File) -> - case do_read(Fd, "", StartLine) of - {ok, Row, EndLine} -> - ?vtrace("loop -> " - "~n Row: ~p" - "~n EndLine: ~p", [Row, EndLine]), - case (catch Check(Row)) of - ok -> - ?vtrace("loop -> ok", []), - loop(Fd, [Row | Res], Check, EndLine, File); - {ok, NewRow} -> - ?vtrace("loop -> ok: " - "~n NewRow: ~p", [NewRow]), - loop(Fd, [NewRow | Res], Check, EndLine, File); - {error, Reason} -> - ?vtrace("loop -> check error: " - "~n Reason: ~p", [Reason]), - {error, {failed_check, File, StartLine, EndLine, Reason}}; - Error -> - ?vtrace("loop -> check failure: " - "~n Error: ~p", [Error]), - {error, {failed_check, File, StartLine, EndLine, Error}} - end; - {error, Error, EndLine} -> - ?vtrace("loop -> read failure: " - "~n Error: ~p", [Error]), - {error, {failed_reading, File, StartLine, EndLine, Error}}; - {eof, _EndLine} -> - {ok, Res} + {ok, Fd} -> + Fd; + {error, Reason} -> + error({failed_open, File, Reason}) end. - do_read(Io, Prompt, StartLine) -> case io:request(Io, {get_until,Prompt,erl_scan,tokens,[StartLine]}) of - {ok, Toks, EndLine} -> - case erl_parse:parse_term(Toks) of - {ok, Term} -> - {ok, Term, EndLine}; - {error, {Line, erl_parse, Error}} -> - {error, {parse_error, Error}, Line} - end; - Other -> - Other + {ok, Toks, EndLine} -> + case erl_parse:parse_term(Toks) of + {ok, Term} -> + {ok, Term, EndLine}; + {error, {Line, erl_parse, Error}} -> + {error, {parse_error, Error}, Line} + end; + Other -> + Other end. + %%----------------------------------------------------------------- @@ -657,34 +579,12 @@ check_domain(Domain) -> %% --------- %% 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) -> +%% point, so we dont need to do that again, but this function is +%% also used on incoming packets from net_if so a little +%% check that net_if does not supply bad arguments is in order. +%% +mk_taddress(snmpUDPDomain, Address) -> % Legacy 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) -> @@ -693,36 +593,96 @@ mk_taddress(?transportDomainUdpIpv4, Address) -> mk_taddress(transportDomainUdpIpv4, Address); mk_taddress(?transportDomainUdpIpv6, Address) -> mk_taddress(transportDomainUdpIpv6, Address); +%% +mk_taddress(transportDomainUdpIpv4 = Domain, Address) -> + case Address of + {Ip, Port} when tuple_size(Ip) =:= 4, is_integer(Port) -> + tuple_to_list(Ip) ++ mk_bytes(Port); + _ -> + erlang:error(badarg, [Domain,Address]) + end; +mk_taddress(transportDomainUdpIpv6 = Domain, Address) -> + case Address of + {Ip, Port} + when tuple_size(Ip) =:= 8, is_integer(Port) -> + tuple_to_list(Ip) ++ mk_bytes(Port); + _ -> + erlang:error(badarg, [Domain,Address]) + end; %% Bad domain mk_taddress(BadDomain, _) -> error({bad_domain, BadDomain}). -%% XXX remove +%% 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 tuple_size(Ip) =:= 4 -> +%% 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 tuple_size(Ip) == 8 -> +%% 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, []) -> %% Used for empty mask +%% []; +%% mk_taddress(Domain, Address) -> +%% 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}). -mk_taddress(snmpUDPDomain, Ip, Port) -> - mk_taddress(transportDomainUdpIpv4, Ip, Port); -mk_taddress(transportDomainUdpIpv4, Ip, Port) when is_list(Ip) -> - Ip ++ [Port div 256, Port rem 256]; -mk_taddress(transportDomainUdpIpv4 = Domain, Ip, Port) when is_tuple(Ip) -> - mk_taddress(Domain, tuple_to_list(Ip), Port); -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); -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}). + + +%% %% XXX remove + +%% mk_taddress(snmpUDPDomain, Ip, Port) -> +%% mk_taddress(transportDomainUdpIpv4, Ip, Port); +%% mk_taddress(transportDomainUdpIpv4, Ip, Port) when is_list(Ip) -> +%% Ip ++ [Port div 256, Port rem 256]; +%% mk_taddress(transportDomainUdpIpv4 = Domain, Ip, Port) when is_tuple(Ip) -> +%% mk_taddress(Domain, tuple_to_list(Ip), Port); +%% 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); +%% 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}). %% --------- @@ -779,59 +739,128 @@ check_ip(BadDomain, _X) -> %% Check a configuration term field from a file to see if it %% can be fed to mk_taddress/2. -check_address(Domain, Address) +check_address(Domain, Address, DefaultPort) -> + case check_address_ip(Domain, Address) of + false -> + case check_address_ip_port(Domain, Address) of + false -> + error({invalid_address, {Domain, Address}}); + true -> + {ok, Address}; + FixedAddress -> + {ok, FixedAddress} + end; + true -> + {ok, {Address, DefaultPort}}; + FixedIp -> + {ok, {FixedIp, DefaultPort}} + end. + +check_address(Domain, Address) -> + case check_address_ip_port(Domain, Address) of + false -> + error({invalid_address, {Domain, Address}}); + true -> + {ok, Address}; + FixedAddress -> + {ok, FixedAddress} + end. + +%% -> IP +check_address_ip(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; + {A0, A1, A2, A3} + when ?is_ipv4_addr(A0, A1, A2, A3) -> + true; %% Erlangish format - {[A0,A1,A2,A3], P} - when ?is_ipv4_addr(A0, A1, A2, A3), ?is_word(P) -> - ok; + [A0,A1,A2,A3] + when ?is_ipv4_addr(A0, A1, A2, A3) -> + {A0, A1, A2, A3}; + _ -> + false + end; +check_address_ip(transportDomainUdpIpv6, Address) -> + case Address of + %% Erlang native format + {A0, A1, A2, A3, A4, A5, A6, A7} + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7) -> + true; + %% Erlangish format + [A0,A1,A2,A3,A4,A5,A6,A7] + when ?is_ipv6_addr(A0, A1, A2, A3, A4, A5, A6, A7) -> + {A0, A1, A2, A3, A4, A5, A6, A7}; + %% SNMP standards format + [A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15] + when ?is_ipv6_addr( + A0, A1, A2, A3, A4, A5, A6, A7, + A8, A9, A10, A11, A12, A13, A14, A15) -> + {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)}; + _ -> + false + end. + +%% -> {IP, Port} +check_address_ip_port(Domain, Address) + when Domain =:= snmpUDPDomain; + Domain =:= transportDomainUdpIpv4 -> + case Address of + {IP, Port} when ?is_word(Port) -> + case check_address_ip(Domain, IP) of + false -> + false; + true -> + Address; + FixedIP -> + {FixedIP, Port} + end; %% SNMP standards format [A0,A1,A2,A3,P0,P1] when ?is_ipv4_addr(A0, A1, A2, A3), ?is_word(P0, P1) -> - ok; + {{A0, A1, A2, A3}, mk_word(P0, P1)}; _ -> - error({invalid_address, {Domain, Address}}) + false end; -check_address(transportDomainUdpIpv6 = Domain, Address) -> +check_address_ip_port(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; + {IP, Port} when ?is_word(Port) -> + case check_address_ip(Domain, IP) of + false -> + false; + true -> + Address; + FixedIP -> + {FixedIP, Port} + end; %% 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; + {{A0, A1, A2, A3, A4, A5, A6, A7}, P}; %% 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; + {{A0, A1, A2, A3, A4, A5, A6, A7}, mk_word(P0, P1)}; %% 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; + {{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)}, + mk_word(P0, P1)}; _ -> - error({invalid_address, {Domain, Address}}) - end; -check_address(BadDomain, _) -> - error({invalid_domain, BadDomain}). + false + end. -- cgit v1.2.3