PageRenderTime 85ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/snmp/src/manager/snmpm_config.erl

https://github.com/bsmr-erlang/otp
Erlang | 3436 lines | 2667 code | 443 blank | 326 comment | 12 complexity | fc2c18c5dd9e4923635fb9af07858fcd MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. %%
  2. %% %CopyrightBegin%
  3. %%
  4. %% Copyright Ericsson AB 2004-2016. All Rights Reserved.
  5. %%
  6. %% Licensed under the Apache License, Version 2.0 (the "License");
  7. %% you may not use this file except in compliance with the License.
  8. %% You may obtain a copy of the License at
  9. %%
  10. %% http://www.apache.org/licenses/LICENSE-2.0
  11. %%
  12. %% Unless required by applicable law or agreed to in writing, software
  13. %% distributed under the License is distributed on an "AS IS" BASIS,
  14. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. %% See the License for the specific language governing permissions and
  16. %% limitations under the License.
  17. %%
  18. %% %CopyrightEnd%
  19. %%
  20. %% -------------------------------------------------------------------------
  21. %%
  22. %% Some of the stuff stored here should really be persistent!!
  23. %% (e.g. snmp-engine-boot)
  24. %%
  25. %% -------------------------------------------------------------------------
  26. -module(snmpm_config).
  27. -behaviour(gen_server).
  28. %% External exports
  29. %% Avoid warning for local function error/1 clashing with autoimported BIF.
  30. -compile({no_auto_import,[error/1]}).
  31. -export([start_link/1, stop/0, is_started/0]).
  32. -export([register_user/4, unregister_user/1,
  33. which_users/0,
  34. user_info/0, user_info/1, user_info/2,
  35. register_agent/3, unregister_agent/2,
  36. agent_info/0, agent_info/2, agent_info/3,
  37. update_agent_info/3, update_agent_info/4,
  38. which_agents/0, which_agents/1,
  39. is_known_engine_id/2,
  40. get_agent_engine_id/1,
  41. get_agent_engine_max_message_size/1,
  42. get_agent_version/1,
  43. get_agent_mp_model/1,
  44. get_agent_user_id/1, get_agent_user_id/2,
  45. get_agent_user_info/2,
  46. system_info/0, system_info/1,
  47. %% update_system_info/2,
  48. get_engine_id/0, get_engine_max_message_size/0,
  49. register_usm_user/3, unregister_usm_user/2,
  50. which_usm_users/0, which_usm_users/1,
  51. usm_user_info/3, update_usm_user_info/4,
  52. get_usm_user/2, get_usm_user_from_sec_name/2,
  53. is_usm_engine_id_known/1,
  54. get_engine_boots/0, get_engine_time/0,
  55. set_engine_boots/1, set_engine_time/1,
  56. get_usm_eboots/1, get_usm_etime/1, get_usm_eltime/1,
  57. set_usm_eboots/2, set_usm_etime/2, set_usm_eltime/2,
  58. reset_usm_cache/1,
  59. cre_counter/2,
  60. incr_counter/2,
  61. increment_counter/3, increment_counter/4,
  62. cre_stats_counter/2,
  63. maybe_cre_stats_counter/2,
  64. incr_stats_counter/2,
  65. reset_stats_counter/1,
  66. get_stats_counters/0, get_stats_counter/1,
  67. load_mib/1, unload_mib/1, which_mibs/0,
  68. make_mini_mib/0,
  69. name_to_oid/1, oid_to_name/1, oid_to_type/1,
  70. system_start_time/0,
  71. info/0,
  72. verbosity/1,
  73. backup/1,
  74. mk_target_name/3,
  75. default_transport_domain/0
  76. ]).
  77. %% Backward compatibillity exports
  78. -export([
  79. register_user/3,
  80. unregister_agent/3,
  81. update_agent_info/5,
  82. is_known_engine_id/3,
  83. get_agent_engine_id/2,
  84. get_agent_engine_max_message_size/2,
  85. get_agent_version/2,
  86. get_agent_mp_model/2
  87. ]).
  88. -export([
  89. order_manager_config/2,
  90. check_manager_config/2,
  91. check_user_config/1,
  92. check_agent_config/1,
  93. check_usm_user_config/1]).
  94. %% gen_server callbacks
  95. -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
  96. code_change/3, terminate/2]).
  97. %% Includes:
  98. -include_lib("kernel/include/file.hrl").
  99. -include("snmp_types.hrl").
  100. -include("snmpm_internal.hrl").
  101. -include("snmpm_usm.hrl").
  102. -include("snmp_debug.hrl").
  103. -include("snmp_verbosity.hrl").
  104. %% Types:
  105. -record(user, {id, mod, data, default_agent_config}).
  106. -record(state, {backup}).
  107. %% Macros and Constants:
  108. -define(SERVER, ?MODULE).
  109. -define(BACKUP_DB, snmpm_config_backup).
  110. -define(CONFIG_DB, snmpm_config_db).
  111. -define(DEFAULT_USER, default_user).
  112. -define(DEFAULT_AGENT_PORT, 161).
  113. -define(IRB_DEFAULT, auto).
  114. %% -define(IRB_DEFAULT, {user, timer:seconds(15)}).
  115. -define(USER_MOD_DEFAULT, snmpm_user_default).
  116. -define(USER_DATA_DEFAULT, undefined).
  117. %% -define(DEF_ADDR_TAG, default_addr_tag).
  118. -define(DEFAULT_TARGETNAME, default_agent).
  119. -define(DEF_PORT_TAG, default_port_tag).
  120. -define(SUPPORTED_DOMAINS, [transportDomainUdpIpv4, transportDomainUdpIpv6]).
  121. -ifdef(snmp_debug).
  122. -define(GS_START_LINK(Opts),
  123. gen_server:start_link({local, ?SERVER}, ?MODULE, [Opts],
  124. [{debug,[trace]}])).
  125. -else.
  126. -define(GS_START_LINK(Opts),
  127. gen_server:start_link({local, ?SERVER}, ?MODULE, [Opts], [])).
  128. -endif.
  129. %%%-------------------------------------------------------------------
  130. %%% API
  131. %%%-------------------------------------------------------------------
  132. default_transport_domain() ->
  133. snmpUDPDomain.
  134. start_link(Opts) ->
  135. ?d("start_link -> entry with"
  136. "~n Opts: ~p", [Opts]),
  137. ?GS_START_LINK(Opts).
  138. stop() ->
  139. call(stop).
  140. is_started() ->
  141. call(is_started, 1000).
  142. backup(BackupDir) when is_list(BackupDir) ->
  143. call({backup, BackupDir}).
  144. %% Backward compatibillity
  145. register_user(UserId, UserMod, UserData) ->
  146. register_user(UserId, UserMod, UserData, []).
  147. register_user(UserId, UserMod, UserData, DefaultAgentConfig)
  148. when (UserId =/= ?DEFAULT_USER) andalso is_list(DefaultAgentConfig) ->
  149. case (catch verify_user_behaviour(UserMod)) of
  150. ok ->
  151. {ok, SystemDefaultAgentConfig} = agent_info(),
  152. Config =
  153. ensure_config(SystemDefaultAgentConfig,
  154. DefaultAgentConfig),
  155. %% Config = default_agent_config(DefaultAgentConfig),
  156. call({register_user, UserId, UserMod, UserData, Config});
  157. Error ->
  158. Error
  159. end;
  160. register_user(UserId, _UserMod, _UserData, DefaultAgentConfig)
  161. when (UserId =/= ?DEFAULT_USER) ->
  162. {error, {bad_default_agent_config, DefaultAgentConfig}};
  163. register_user(UserId, _, _, _) ->
  164. {error, {bad_user_id, UserId}}.
  165. %% default_agent_config(DefaultAgentConfig) ->
  166. %% {ok, SystemDefaultAgentConfig} = agent_info(),
  167. %% default_agent_config(SystemDefaultAgentConfig, DefaultAgentConfig).
  168. %% default_agent_config([], DefaultAgentConfig) ->
  169. %% DefaultAgentConfig;
  170. %% default_agent_config([{Key, _} = Entry|T], DefaultAgentConfig) ->
  171. %% case lists:keymember(Key, 1, DefaultAgentConfig) of
  172. %% true ->
  173. %% default_agent_config(T, DefaultAgentConfig);
  174. %% false ->
  175. %% default_agent_config(T, [Entry|DefaultAgentConfig])
  176. %% end.
  177. verify_user_behaviour(UserMod) ->
  178. case snmp_misc:verify_behaviour(snmpm_user, UserMod) of
  179. ok ->
  180. ok;
  181. Error ->
  182. %% This user may implement the old behaviour, check it
  183. case snmp_misc:verify_behaviour(snmpm_user_old, UserMod) of
  184. ok ->
  185. ok;
  186. _ ->
  187. throw(Error)
  188. end
  189. end.
  190. unregister_user(UserId) when UserId =/= ?DEFAULT_USER ->
  191. call({unregister_user, UserId});
  192. unregister_user(BadUserId) ->
  193. {error, {bad_user_id, BadUserId}}.
  194. which_users() ->
  195. Pattern = #user{id = '$1', _ = '_'},
  196. Match = ets:match(snmpm_user_table, Pattern),
  197. [UserId || [UserId] <- Match, UserId =/= ?DEFAULT_USER].
  198. user_info() ->
  199. UserId = ?DEFAULT_USER,
  200. case user_info(UserId) of
  201. {ok, Mod, Data} ->
  202. {ok, UserId, Mod, Data};
  203. Error ->
  204. Error
  205. end.
  206. user_info(UserId) ->
  207. case ets:lookup(snmpm_user_table, UserId) of
  208. [#user{mod = UserMod, data = UserData}] ->
  209. {ok, UserMod, UserData};
  210. _ ->
  211. {error, not_found}
  212. end.
  213. user_info(UserId, Item) ->
  214. case (catch do_user_info(UserId, Item)) of
  215. {'EXIT', _} ->
  216. {error, {not_found, Item}};
  217. Val ->
  218. {ok, Val}
  219. end.
  220. do_user_info(UserId, module) ->
  221. ets:lookup_element(snmpm_user_table, UserId, #user.mod);
  222. do_user_info(UserId, data) ->
  223. ets:lookup_element(snmpm_user_table, UserId, #user.data);
  224. do_user_info(UserId, default_agent_config) ->
  225. ets:lookup_element(snmpm_user_table, UserId, #user.default_agent_config);
  226. do_user_info(_UserId, BadItem) ->
  227. error({not_found, BadItem}).
  228. %% A target-name constructed in this way is a string with the following:
  229. %% <IP-address>:<Port>-<Version>
  230. %% This is intended for backward compatibility and therefore has
  231. %% only support for IPv4 addresses and *no* other transport domain.
  232. mk_target_name(Domain, Addr, Config)
  233. when is_atom(Domain), is_list(Config) ->
  234. Version =
  235. case lists:keysearch(version, 1, Config) of
  236. {value, {_, V}} ->
  237. V;
  238. false ->
  239. select_lowest_supported_version()
  240. end,
  241. try
  242. lists:flatten(
  243. io_lib:format(
  244. "~s-~w", [snmp_conf:mk_addr_string({Domain, Addr}), Version]))
  245. catch
  246. _ ->
  247. lists:flatten(
  248. io_lib:format("~p-~w", [Addr, Version]))
  249. end;
  250. mk_target_name(Ip, Port, Config)
  251. when is_integer(Port), is_list(Config) ->
  252. Domain = default_transport_domain(),
  253. try fix_address(Domain, {Ip, Port}) of
  254. Address ->
  255. mk_target_name(Domain, Address, Config)
  256. catch
  257. _ ->
  258. Version =
  259. case lists:keysearch(version, 1, Config) of
  260. {value, {_, V}} ->
  261. V;
  262. false ->
  263. select_lowest_supported_version()
  264. end,
  265. lists:flatten(
  266. io_lib:format("~p:~w-~w", [Ip, Port, Version]))
  267. end.
  268. select_lowest_supported_version() ->
  269. {ok, Versions} = system_info(versions),
  270. select_lowest_supported_version([v1, v2, v3], Versions).
  271. select_lowest_supported_version([], Versions) ->
  272. error({bad_versions, Versions});
  273. select_lowest_supported_version([H|T], Versions) ->
  274. case lists:member(H, Versions) of
  275. true ->
  276. H;
  277. false ->
  278. select_lowest_supported_version(T, Versions)
  279. end.
  280. register_agent(UserId, _TargetName, _Config0) when (UserId =:= user_id) ->
  281. {error, {bad_user_id, UserId}};
  282. register_agent(UserId, TargetName, Config0)
  283. when (is_list(TargetName) andalso
  284. (length(TargetName) > 0) andalso
  285. is_list(Config0)) ->
  286. ?vtrace("register_agent -> entry with"
  287. "~n UserId: ~p"
  288. "~n TargetName: ~p"
  289. "~n Config0: ~p", [UserId, TargetName, Config0]),
  290. %% Check:
  291. %% 1) That the mandatory configs are present
  292. %% 2) That no illegal config, e.g. user_id (used internally),
  293. %% is not present
  294. %% 3) Check that there are no invalid or erroneous configs
  295. %% 4) Check that the manager is capable of using the selected version
  296. try
  297. verify_mandatory(Config0, [engine_id, reg_type]),
  298. verify_someof(Config0, [address, taddress]),
  299. verify_illegal(Config0, [user_id]),
  300. Config = verify_agent_config(Config0),
  301. Vsns = versions(),
  302. Vsn = which_version(Config),
  303. verify_version(Vsn, Vsns),
  304. call({register_agent, UserId, TargetName, Config})
  305. catch
  306. Error ->
  307. Error
  308. end.
  309. versions() ->
  310. case system_info(versions) of
  311. {ok, Vsns} ->
  312. Vsns;
  313. {error, _} = ERROR ->
  314. throw(ERROR)
  315. end.
  316. which_version(Conf) ->
  317. case lists:keysearch(version, 1, Conf) of
  318. {value, {version, V}} ->
  319. V;
  320. false ->
  321. v1
  322. end.
  323. verify_version(Vsn, Vsns) ->
  324. case lists:member(Vsn, Vsns) of
  325. true ->
  326. ok;
  327. false ->
  328. Reason = {version_not_supported_by_manager, Vsn, Vsns},
  329. error(Reason)
  330. end.
  331. unregister_agent(UserId, TargetName) ->
  332. call({unregister_agent, UserId, TargetName}).
  333. %% This is the old style agent unregistration (using Addr and Port).
  334. unregister_agent(UserId, Domain, Address) when is_atom(Domain) ->
  335. try fix_address(Domain, Address) of
  336. NAddress ->
  337. do_unregister_agent(UserId, Domain, NAddress)
  338. catch
  339. _ ->
  340. {error, not_found}
  341. end;
  342. unregister_agent(UserId, Ip, Port) when is_integer(Port) ->
  343. Domain = default_transport_domain(),
  344. try fix_address(Domain, {Ip, Port}) of
  345. Address ->
  346. do_unregister_agent(UserId, Domain, Address)
  347. catch
  348. _ ->
  349. {error, not_found}
  350. end.
  351. do_unregister_agent(UserId, Domain, Address) ->
  352. case do_agent_info(Domain, Address, target_name) of
  353. {ok, TargetName} ->
  354. unregister_agent(UserId, TargetName);
  355. Error ->
  356. Error
  357. end.
  358. agent_info() ->
  359. agent_info(?DEFAULT_TARGETNAME, all).
  360. agent_info(TargetName, all) ->
  361. case ets:match_object(snmpm_agent_table, {{TargetName, '_'}, '_'}) of
  362. [] ->
  363. {error, not_found};
  364. All ->
  365. {ok, [{Item, Val} || {{_, Item}, Val} <- All]}
  366. end;
  367. %% Begin backwards compatibility
  368. agent_info(TargetName, address) ->
  369. case agent_info({TargetName, taddress}) of
  370. {ok, Val} ->
  371. {Addr, _} = Val,
  372. {ok, Addr};
  373. _ ->
  374. %% This should be redundant since 'taddress' should exist
  375. agent_info({TargetName, address})
  376. end;
  377. agent_info(TargetName, port) ->
  378. case agent_info({TargetName, taddress}) of
  379. {ok, Val} ->
  380. {_, Port} = Val,
  381. {ok, Port};
  382. _ ->
  383. %% This should be redundant since 'taddress' should exist
  384. agent_info({TargetName, port})
  385. end;
  386. %% End backwards compatibility
  387. agent_info(TargetName, Item) ->
  388. agent_info({TargetName, Item}).
  389. agent_info(Key) ->
  390. case ets:lookup(snmpm_agent_table, Key) of
  391. [{_, Val}] ->
  392. {ok, Val};
  393. [] ->
  394. {error, not_found}
  395. end.
  396. agent_info(Domain, Address, Item) when is_atom(Domain) ->
  397. try fix_address(Domain, Address) of
  398. NAddress ->
  399. do_agent_info(Domain, NAddress, Item)
  400. catch
  401. _Thrown ->
  402. %% p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n"
  403. %% " ~p",
  404. %% [Domain, Address, Item, _Thrown, erlang:get_stacktrace()]),
  405. {error, not_found}
  406. end;
  407. agent_info(Ip, Port, Item) when is_integer(Port) ->
  408. %% p(?MODULE_STRING":agent_info(~p, ~p, ~p) entry~n",
  409. %% [Ip, Port, Item]),
  410. Domain = default_transport_domain(),
  411. try fix_address(Domain, {Ip, Port}) of
  412. Address ->
  413. do_agent_info(Domain, Address, Item)
  414. catch
  415. _Thrown ->
  416. %% p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n"
  417. %% " ~p",
  418. %% [Ip, Port, Item, _Thrown, erlang:get_stacktrace()]),
  419. {error, not_found}
  420. end.
  421. do_agent_info(Domain, Address, target_name = Item) ->
  422. %% p(?MODULE_STRING":do_agent_info(~p, ~p, ~p) entry~n",
  423. %% [Domain, Address, Item]),
  424. case ets:lookup(snmpm_agent_table, {Domain, Address, Item}) of
  425. [{_, Val}] ->
  426. {ok, Val};
  427. [] ->
  428. {error, not_found}
  429. end;
  430. do_agent_info(Domain, Address, Item) ->
  431. %% p(?MODULE_STRING":do_agent_info(~p, ~p, ~p) entry~n",
  432. %% [Domain, Address, Item]),
  433. case do_agent_info(Domain, Address, target_name) of
  434. {ok, TargetName} ->
  435. agent_info(TargetName, Item);
  436. Error ->
  437. Error
  438. end.
  439. ensure_agent_info(_, [], Info) ->
  440. Info;
  441. ensure_agent_info(TargetName, [Item|Items], Info) ->
  442. case lists:keymember(Item, 1, Info) of
  443. true ->
  444. ensure_agent_info(TargetName, Items, Info);
  445. false ->
  446. {ok, Value} = agent_info(TargetName, Item),
  447. ensure_agent_info(TargetName, Items, [{Item, Value}|Info])
  448. end.
  449. which_agents() ->
  450. which_agents('_').
  451. which_agents(UserId) ->
  452. Pat = {{'$1', user_id}, UserId},
  453. Agents = ets:match(snmpm_agent_table, Pat),
  454. [TargetName || [TargetName] <- Agents].
  455. update_agent_info(UserId, TargetName, Info) ->
  456. call({update_agent_info, UserId, TargetName, Info}).
  457. %% <BACKWARD-COMPAT-2>
  458. %% This is wrapped in the interface module, so this function is
  459. %% only here to catch code-upgrade problems.
  460. update_agent_info(UserId, TargetName, Item, Val) ->
  461. update_agent_info(UserId, TargetName, [{Item, Val}]).
  462. %% </BACKWARD-COMPAT-2>
  463. %% <BACKWARD-COMPAT-1>
  464. update_agent_info(UserId, Addr, Port, Item, Val) ->
  465. case agent_info(Addr, Port, target_name) of
  466. {ok, TargetName} ->
  467. update_agent_info(UserId, TargetName, Item, Val);
  468. Error ->
  469. Error
  470. end.
  471. %% </BACKWARD-COMPAT-1>
  472. is_known_engine_id(EngineID, TargetName) ->
  473. case agent_info(TargetName, engine_id) of
  474. {ok, EngineID} ->
  475. true;
  476. {ok, _OtherEngineID} ->
  477. false;
  478. _ ->
  479. false
  480. end.
  481. %% Backward compatibillity
  482. is_known_engine_id(EngineID, Addr, Port) ->
  483. case agent_info(Addr, Port, target_name) of
  484. {ok, TargetName} ->
  485. is_known_engine_id(EngineID, TargetName);
  486. _ ->
  487. false
  488. end.
  489. get_agent_engine_id(TargetName) ->
  490. agent_info(TargetName, engine_id).
  491. %% Backward compatibillity
  492. get_agent_engine_id(Addr, Port) ->
  493. agent_info(Addr, Port, engine_id).
  494. get_agent_engine_max_message_size(TargetName) ->
  495. agent_info(TargetName, max_message_size).
  496. %% Backward compatibillity
  497. get_agent_engine_max_message_size(Addr, Port) ->
  498. agent_info(Addr, Port, max_message_size).
  499. get_agent_version(TargetName) ->
  500. agent_info(TargetName, version).
  501. %% Backward compatibillity
  502. get_agent_version(Addr, Port) ->
  503. agent_info(Addr, Port, version).
  504. get_agent_mp_model(TargetName) ->
  505. case agent_info(TargetName, version) of
  506. {ok, v2} ->
  507. {ok, v2c};
  508. {ok, V} ->
  509. {ok, V};
  510. Err ->
  511. Err
  512. end.
  513. %% Backward compatibillity
  514. get_agent_mp_model(Addr, Port) ->
  515. case agent_info(Addr, Port, target_name) of
  516. {ok, TargetName} ->
  517. get_agent_mp_model(TargetName);
  518. Error ->
  519. Error
  520. end.
  521. get_agent_user_id(TargetName) ->
  522. agent_info(TargetName, user_id).
  523. get_agent_user_id(Addr, Port) ->
  524. agent_info(Addr, Port, user_id).
  525. get_agent_user_info(Addr, Port) ->
  526. case agent_info(Addr, Port, target_name) of
  527. {ok, Target} ->
  528. case agent_info(Target, reg_type) of
  529. {ok, RegType} ->
  530. case agent_info(Target, user_id) of
  531. {ok, UserId} ->
  532. {ok, UserId, Target, RegType};
  533. {error, not_found} ->
  534. {error, {user_id_not_found, Target}}
  535. end;
  536. {error, not_found} ->
  537. {error, {reg_type_not_found, Target}}
  538. end;
  539. {error, not_found} ->
  540. {error, {target_name_not_found, Addr, Port}}
  541. end.
  542. system_info() ->
  543. system_info(all).
  544. system_info(all) ->
  545. lists:sort(ets:tab2list(snmpm_config_table));
  546. system_info(Key) when is_atom(Key) ->
  547. case ets:lookup(snmpm_config_table, Key) of
  548. [{_, Val}] ->
  549. {ok, Val};
  550. _ ->
  551. {error, not_found}
  552. end.
  553. %% update_system_info(Key, Val) ->
  554. %% call({update_system_info, Key, Val}).
  555. system_start_time() ->
  556. system_info(system_start_time).
  557. get_engine_id() ->
  558. system_info(engine_id).
  559. get_engine_max_message_size() ->
  560. system_info(max_message_size).
  561. get_engine_boots() ->
  562. case dets:lookup(?CONFIG_DB, snmp_engine_boots) of
  563. [{_, Boots}] ->
  564. {ok, Boots};
  565. _ ->
  566. {error, not_found}
  567. end.
  568. set_engine_boots(Boots) ->
  569. case (whereis(?SERVER) =:= self()) of
  570. false ->
  571. call({set_engine_boots, Boots});
  572. true ->
  573. dets:insert(?CONFIG_DB, {snmp_engine_boots, Boots}),
  574. ok
  575. end.
  576. get_engine_time() ->
  577. case system_info(snmp_engine_base) of
  578. {ok, EngineBase} ->
  579. {ok, snmp_misc:now(sec) - EngineBase};
  580. Error ->
  581. Error
  582. end.
  583. get_usm_eboots(SnmpEngineID) ->
  584. Key = {eboots, SnmpEngineID},
  585. case get_usm_cache(Key) of
  586. {ok, Boots} ->
  587. {ok, Boots};
  588. _ ->
  589. {ok, 0}
  590. end.
  591. get_usm_etime(SnmpEngineID) ->
  592. Key = {etime, SnmpEngineID},
  593. case get_usm_cache(Key) of
  594. {ok, Diff} ->
  595. {ok, snmp_misc:now(sec) - Diff};
  596. _ ->
  597. {ok, 0}
  598. end.
  599. get_usm_eltime(SnmpEngineID) ->
  600. Key = {eltime, SnmpEngineID},
  601. case get_usm_cache(Key) of
  602. {ok, Time} ->
  603. {ok, Time};
  604. _ ->
  605. {ok, 0}
  606. end.
  607. get_usm_cache(Key) ->
  608. case ets:lookup(snmpm_usm_table, {usm_cache, Key}) of
  609. [{_, Val}] ->
  610. {ok, Val};
  611. _ ->
  612. {error, not_found}
  613. end.
  614. set_usm_eboots(SnmpEngineID, EngineBoots) ->
  615. set_usm_cache({eboots, SnmpEngineID}, EngineBoots).
  616. set_usm_etime(SnmpEngineID, Diff) ->
  617. set_usm_cache({etime, SnmpEngineID}, Diff).
  618. set_usm_eltime(SnmpEngineID, Time) ->
  619. set_usm_cache({eltime, SnmpEngineID}, Time).
  620. set_usm_cache(Key, Val) ->
  621. call({set_usm_cache, Key, Val}).
  622. reset_usm_cache(SnmpEngineID) ->
  623. case (whereis(?SERVER) =:= self()) of
  624. false ->
  625. call({reset_usm_cache, SnmpEngineID});
  626. true ->
  627. Pat = {{usm_cache, {'_', SnmpEngineID}}, '_'},
  628. ets:match_delete(snmpm_usm_table, Pat),
  629. ok
  630. end.
  631. set_engine_time(Time) ->
  632. call({set_engine_time, Time}).
  633. register_usm_user(EngineID, Name, Config)
  634. when is_list(EngineID) andalso is_list(Name) ->
  635. case verify_usm_user_config(EngineID, Name, Config) of
  636. {ok, User} ->
  637. call({register_usm_user, User});
  638. Error ->
  639. Error
  640. end.
  641. unregister_usm_user(EngineID, Name)
  642. when is_list(EngineID) andalso is_list(Name) ->
  643. call({unregister_usm_user, EngineID, Name}).
  644. verify_usm_user_config(EngineID, Name, Config) ->
  645. try
  646. begin
  647. verify_mandatory(Config, []),
  648. verify_illegal(Config, [engine_id, name]),
  649. verify_usm_user_config2(EngineID, Name, Config)
  650. end
  651. catch
  652. throw:Error ->
  653. Error
  654. end.
  655. verify_usm_user_config2(EngineID, Name, Config) ->
  656. SecName = verify_usm_user_get(sec_name, Name, Config),
  657. Auth = verify_usm_user_get(auth, usmNoAuthProtocol, Config),
  658. AuthKey = verify_usm_user_get(auth_key, [], Config),
  659. Priv = verify_usm_user_get(priv, usmNoPrivProtocol, Config),
  660. PrivKey = verify_usm_user_get(priv_key, [], Config),
  661. User = {EngineID, Name, SecName, Auth, AuthKey, Priv, PrivKey},
  662. verify_usm_user(User).
  663. verify_usm_user_get(Item, Default, Config) ->
  664. case lists:keysearch(Item, 1, Config) of
  665. {value, {_, Val}} ->
  666. Val;
  667. false ->
  668. Default
  669. end.
  670. which_usm_users() ->
  671. Pattern = {usm_key('$1', '$2'), '_'},
  672. Match = ets:match(snmpm_usm_table, Pattern),
  673. [{EngineID, UserName} || [EngineID, UserName] <- Match].
  674. which_usm_users(EngineID) ->
  675. Pattern = {usm_key(EngineID, '$1'), '_'},
  676. Match = ets:match(snmpm_usm_table, Pattern),
  677. [UserName || [UserName] <- Match].
  678. usm_user_info(EngineID, UserName, Item) ->
  679. case ets:lookup(snmpm_usm_table, usm_key(EngineID, UserName)) of
  680. [] ->
  681. {error, not_found};
  682. [{_Key, UsmUser}] ->
  683. do_usm_user_info(UsmUser, Item)
  684. end.
  685. do_usm_user_info(#usm_user{sec_name = SecName}, sec_name) ->
  686. {ok, SecName};
  687. do_usm_user_info(#usm_user{auth = AuthP}, auth) ->
  688. {ok, AuthP};
  689. do_usm_user_info(#usm_user{auth_key = AuthKey}, auth_key) ->
  690. {ok, AuthKey};
  691. do_usm_user_info(#usm_user{priv = PrivP}, priv) ->
  692. {ok, PrivP};
  693. do_usm_user_info(#usm_user{priv_key = PrivKey}, priv_key) ->
  694. {ok, PrivKey};
  695. do_usm_user_info(#usm_user{engine_id = EngineID}, engine_id) ->
  696. {ok, EngineID};
  697. do_usm_user_info(#usm_user{name = Name}, name) ->
  698. {ok, Name};
  699. do_usm_user_info(_, Item) ->
  700. {error, {bad_iten, Item}}.
  701. update_usm_user_info(EngineID, UserName, Item, Val)
  702. when (Item =/= engine_id) andalso (Item =/= name) ->
  703. call({update_usm_user_info, EngineID, UserName, Item, Val}).
  704. get_usm_user(EngineID, UserName) ->
  705. Key = usm_key(EngineID, UserName),
  706. case ets:lookup(snmpm_usm_table, Key) of
  707. [{_, User}] ->
  708. {ok, User};
  709. _ ->
  710. {error, not_found}
  711. end.
  712. is_usm_engine_id_known(EngineID) ->
  713. Pattern = {usm_key(EngineID, '$1'), '_'},
  714. case ets:match(snmpm_usm_table, Pattern) of
  715. [] ->
  716. false;
  717. _ ->
  718. true
  719. end.
  720. get_usm_user_from_sec_name(EngineID, SecName) ->
  721. %% Since the normal mapping between UserName and SecName is the
  722. %% identity-function, we first try to use the SecName as UserName,
  723. %% and check the resulting row. If it doesn't match, we'll have to
  724. %% loop through the entire table.
  725. Key = usm_key(EngineID, SecName),
  726. case ets:lookup(snmpm_usm_table, Key) of
  727. [{Key, #usm_user{sec_name = SecName} = User}] ->
  728. {ok, User};
  729. _ ->
  730. %% That did not work, so we have to search
  731. Pattern = {usm_key(EngineID, '_'),
  732. #usm_user{sec_name = SecName, _ = '_'}},
  733. case ets:match_object(snmpm_usm_table, Pattern) of
  734. [{_, User}|_] ->
  735. {ok, User};
  736. _ ->
  737. {error, not_found}
  738. end
  739. end.
  740. %% Wrap-counters (wrapping at 2147483647 or 4294967295)
  741. cre_counter(Counter, Initial) ->
  742. case (whereis(?SERVER) =:= self()) of
  743. false ->
  744. call({cre_counter, Counter, Initial});
  745. true ->
  746. ets:insert(snmpm_counter_table, {Counter, Initial}),
  747. Initial
  748. end.
  749. incr_counter(usm_salt, Incr) -> % Backward compatibillity (upgrade)
  750. incr_counter(usm_des_salt, Incr); % Backward compatibillity (upgrade)
  751. incr_counter(usm_des_salt, Incr) ->
  752. incr_counter(usm_des_salt, Incr, 4294967295);
  753. incr_counter(usm_aes_salt, Incr) ->
  754. incr_counter(usm_aes_salt, Incr, 36893488147419103231);
  755. incr_counter(Counter, Incr) ->
  756. incr_counter(Counter, Incr, 2147483647).
  757. incr_counter(Counter, Incr, Wrap) ->
  758. case (catch ets:update_counter(snmpm_counter_table, Counter, Incr)) of
  759. {'EXIT', _} ->
  760. cre_counter(Counter, Incr);
  761. NewVal when NewVal =< Wrap ->
  762. NewVal;
  763. N ->
  764. cre_counter(Counter, N - Wrap)
  765. end.
  766. %% <ATL Sequence Number>
  767. increment_counter(Counter, Initial, Max) ->
  768. Increment = 1,
  769. increment_counter(Counter, Initial, Increment, Max).
  770. increment_counter(Counter, Initial, Increment, Max) ->
  771. %% This is to make sure no one else increments our counter
  772. Key = {Counter, self()},
  773. %% Counter data
  774. Position = 2,
  775. Threshold = Max,
  776. SetValue = Initial,
  777. UpdateOp = {Position, Increment, Threshold, SetValue},
  778. %% And now for the actual increment
  779. Tab = snmpm_counter_table,
  780. case (catch ets:update_counter(Tab, Key, UpdateOp)) of
  781. {'EXIT', {badarg, _}} ->
  782. %% Oups, first time
  783. ets:insert(Tab, {Key, Initial}),
  784. Initial;
  785. Next when is_integer(Next) ->
  786. Next
  787. end.
  788. %% </ATL Sequence Number>
  789. maybe_cre_stats_counter(Counter, Initial) ->
  790. case ets:lookup(snmpm_stats_table, Counter) of
  791. [_] ->
  792. ok;
  793. _ ->
  794. cre_stats_counter(Counter, Initial)
  795. end.
  796. cre_stats_counter(Counter, Initial) ->
  797. case (whereis(?SERVER) =:= self()) of
  798. false ->
  799. call({cre_stats_counter, Counter, Initial});
  800. true ->
  801. ets:insert(snmpm_stats_table, {Counter, Initial}),
  802. Initial
  803. end.
  804. incr_stats_counter(Counter, Incr) ->
  805. case (catch ets:update_counter(snmpm_stats_table, Counter, Incr)) of
  806. {'EXIT', _} ->
  807. cre_counter(Counter, Incr);
  808. NewVal ->
  809. NewVal
  810. end.
  811. reset_stats_counter(Counter) ->
  812. case (whereis(?SERVER) =:= self()) of
  813. false ->
  814. call({reset_stats_counter, Counter});
  815. true ->
  816. ets:insert(snmpm_stats_table, {Counter, 0})
  817. end,
  818. ok.
  819. get_stats_counter(Counter) ->
  820. case ets:lookup(snmpm_stats_table, Counter) of
  821. [{Counter, Value}] ->
  822. {ok, Value};
  823. _ ->
  824. {error, not_found}
  825. end.
  826. get_stats_counters() ->
  827. ets:tab2list(snmpm_stats_table).
  828. load_mib(Mib) when is_list(Mib) ->
  829. call({load_mib, Mib}).
  830. unload_mib(Mib) when is_list(Mib) ->
  831. call({unload_mib, Mib}).
  832. which_mibs() ->
  833. Pattern = {{mib, '_'}, '$1', '$2'},
  834. Mibs = ets:match(snmpm_mib_table, Pattern),
  835. [list_to_tuple(X) || X <- Mibs].
  836. name_to_oid(Name) ->
  837. Pat = {{mini_mib, '$1'}, Name, '_', '_'},
  838. case ets:match(snmpm_mib_table, Pat) of
  839. [] ->
  840. {error, not_found};
  841. X ->
  842. Oids = [Oid || [Oid] <- X],
  843. {ok, Oids}
  844. end.
  845. oid_to_name(Oid) ->
  846. case ets:lookup(snmpm_mib_table, {mini_mib, Oid}) of
  847. [{_, Name, _, _}] ->
  848. {ok, Name};
  849. [] ->
  850. {error, not_found}
  851. end.
  852. oid_to_type(Oid) ->
  853. case ets:lookup(snmpm_mib_table, {mini_mib, Oid}) of
  854. [{_, _, Type, _}] ->
  855. {ok, Type};
  856. [] ->
  857. {error, not_found}
  858. end.
  859. make_mini_mib() ->
  860. Pat = {{mini_mib, '$1'}, '$2', '$3', '_'},
  861. MiniElems = ets:match(snmpm_mib_table, Pat),
  862. lists:keysort(1, [list_to_tuple(MiniElem) || MiniElem <- MiniElems]).
  863. info() ->
  864. call(info).
  865. verbosity(Verbosity) ->
  866. case ?vvalidate(Verbosity) of
  867. Verbosity ->
  868. call({verbosity, Verbosity});
  869. _ ->
  870. {error, {invalid_verbosity, Verbosity}}
  871. end.
  872. %%%-------------------------------------------------------------------
  873. %%% Callback functions from gen_server
  874. %%%-------------------------------------------------------------------
  875. %%--------------------------------------------------------------------
  876. %% Func: init/1
  877. %% Returns: {ok, State} |
  878. %% {ok, State, Timeout} |
  879. %% ignore |
  880. %% {stop, Reason}
  881. %%--------------------------------------------------------------------
  882. init([Opts]) ->
  883. % put(sname, mconf),
  884. % put(verbosity, trace),
  885. ?d("init -> entry with"
  886. "~n Opts: ~p", [Opts]),
  887. case (catch do_init(Opts)) of
  888. ok ->
  889. {ok, #state{}};
  890. {error, Reason} ->
  891. error_msg("init error: ~p", [Reason]),
  892. {stop, Reason};
  893. {'EXIT', Reason} ->
  894. error_msg("init exit: ~p", [Reason]),
  895. {stop, Reason};
  896. Error ->
  897. error_msg("init failed: ~p", [Error]),
  898. {stop, Error}
  899. end.
  900. do_init(Opts) ->
  901. process_flag(trap_exit, true),
  902. %% Mandatory = [versions, {config, [dir]}],
  903. Mandatory = [{config, [dir, db_dir]}],
  904. verify_options(Opts, Mandatory),
  905. ets:new(snmpm_counter_table, [set, public, named_table, {keypos, 1}]),
  906. ets:new(snmpm_stats_table, [set, public, named_table, {keypos, 1}]),
  907. ets:new(snmpm_mib_table, [set, protected, named_table, {keypos, 1}]),
  908. ets:new(snmpm_config_table, [set, protected, named_table, {keypos, 1}]),
  909. ets:new(snmpm_agent_table, [set, protected, named_table, {keypos, 1}]),
  910. ets:new(snmpm_user_table, [set, protected, named_table, {keypos, 2}]),
  911. ets:new(snmpm_usm_table, [set, protected, named_table, {keypos, 1}]),
  912. %% -- System start time --
  913. ets:insert(snmpm_config_table, {system_start_time, snmp_misc:now(cs)}),
  914. %% --- Own options (dir and db_dir mandatory) ---
  915. ConfOpts = get_opt(config, Opts, []),
  916. ConfVerb = get_opt(verbosity, ConfOpts, silence),
  917. ConfDir = get_opt(dir, ConfOpts),
  918. ConfDbDir = get_opt(db_dir, ConfOpts),
  919. ConfDbInitErr = get_opt(db_init_error, ConfOpts, terminate),
  920. ConfRep = get_opt(repair, ConfOpts, true),
  921. ConfAs = get_opt(auto_save, ConfOpts, 5000),
  922. ets:insert(snmpm_config_table, {config_verbosity, ConfVerb}),
  923. ets:insert(snmpm_config_table, {config_dir, ConfDir}),
  924. ets:insert(snmpm_config_table, {config_db_dir, ConfDbDir}),
  925. ets:insert(snmpm_config_table, {config_db_init_error, ConfDbInitErr}),
  926. ets:insert(snmpm_config_table, {config_repair, ConfRep}),
  927. ets:insert(snmpm_config_table, {config_auto_save, ConfAs}),
  928. put(sname, mconf),
  929. put(verbosity, ConfVerb),
  930. ?vlog("starting", []),
  931. %% -- Create dets file used for storing persistent data --
  932. dets_open(ConfDbDir, ConfDbInitErr, ConfRep, ConfAs),
  933. %% -- Prio (optional) --
  934. Prio = get_opt(priority, Opts, normal),
  935. ets:insert(snmpm_config_table, {prio, Prio}),
  936. try process_flag(priority, Prio)
  937. catch
  938. error:badarg ->
  939. error({invalid_priority,Prio})
  940. end,
  941. %% -- Server (optional) --
  942. ServerOpts = get_opt(server, Opts, []),
  943. ServerVerb = get_opt(verbosity, ServerOpts, silence),
  944. ServerGct = get_opt(timeout, ServerOpts, 30000),
  945. ServerMt = get_opt(multi_threaded, ServerOpts, true),
  946. ets:insert(snmpm_config_table, {server_verbosity, ServerVerb}),
  947. ets:insert(snmpm_config_table, {server_timeout, ServerGct}),
  948. ets:insert(snmpm_config_table, {server_multi_threaded, ServerMt}),
  949. %% -- Mibs (optional) --
  950. ?vdebug("initiate mini mib", []),
  951. Mibs = get_opt(mibs, Opts, []),
  952. ets:insert(snmpm_config_table, {mibs, Mibs}),
  953. init_mini_mib(Mibs),
  954. %% -- Net-if (optional) --
  955. ?vdebug("net_if options", []),
  956. NetIfIrb =
  957. case get_opt(inform_request_behaviour, Opts, ?IRB_DEFAULT) of
  958. user ->
  959. {user, timer:seconds(15)};
  960. Irb ->
  961. Irb
  962. end,
  963. NetIfOpts = get_opt(net_if, Opts, []),
  964. NetIfMod = get_opt(module, NetIfOpts, snmpm_net_if),
  965. NetIfVerb = get_opt(verbosity, NetIfOpts, silence),
  966. NetIfOptions = get_opt(options, NetIfOpts, []),
  967. ets:insert(snmpm_config_table, {net_if_module, NetIfMod}),
  968. ets:insert(snmpm_config_table, {net_if_verbosity, NetIfVerb}),
  969. ets:insert(snmpm_config_table, {net_if_irb, NetIfIrb}),
  970. ets:insert(snmpm_config_table, {net_if_options, NetIfOptions}),
  971. %% -- Versions (optional) --
  972. %% -- Versions (mandatory) ???????????? --
  973. ?vdebug("versions", []),
  974. Vsns = get_opt(versions, Opts, [v1, v2, v3]),
  975. ets:insert(snmpm_config_table, {versions, Vsns}),
  976. %% -- Audit trail log (optional) --
  977. ?vdebug("audit trail log", []),
  978. case get_opt(audit_trail_log, Opts, []) of
  979. [] ->
  980. ?vtrace("no ATL", []),
  981. ets:insert(snmpm_config_table, {audit_trail_log, false});
  982. AuditTrailLogOpts ->
  983. ?vtrace("ATL options: ~p", [AuditTrailLogOpts]),
  984. ets:insert(snmpm_config_table, {audit_trail_log, true}),
  985. LogDir = get_atl_dir(AuditTrailLogOpts),
  986. LogType = get_atl_type(AuditTrailLogOpts),
  987. LogSize = get_atl_size(AuditTrailLogOpts),
  988. LogRep = get_atl_repair(AuditTrailLogOpts),
  989. LogSeqNo = get_atl_seqno(AuditTrailLogOpts),
  990. ets:insert(snmpm_config_table, {audit_trail_log_dir, LogDir}),
  991. ets:insert(snmpm_config_table, {audit_trail_log_type, LogType}),
  992. ets:insert(snmpm_config_table, {audit_trail_log_size, LogSize}),
  993. ets:insert(snmpm_config_table, {audit_trail_log_repair, LogRep}),
  994. ets:insert(snmpm_config_table, {audit_trail_log_seqno, LogSeqNo})
  995. end,
  996. %% -- System default agent config --
  997. ?vdebug("system default agent config", []),
  998. init_agent_default(),
  999. %% -- User (optional) --
  1000. ?vdebug("default user", []),
  1001. DefUserMod = get_opt(def_user_mod, Opts, ?USER_MOD_DEFAULT),
  1002. DefUserData = get_opt(def_user_data, Opts, ?USER_DATA_DEFAULT),
  1003. ets:insert(snmpm_config_table, {def_user_mod, DefUserMod}),
  1004. ets:insert(snmpm_config_table, {def_user_data, DefUserData}),
  1005. {ok, SystemDefaultAgentConfig} = agent_info(),
  1006. DefUser = #user{id = ?DEFAULT_USER,
  1007. mod = DefUserMod,
  1008. data = DefUserData,
  1009. default_agent_config = SystemDefaultAgentConfig},
  1010. ok = handle_register_user(DefUser),
  1011. %% -- Note store --
  1012. ?vdebug("note store", []),
  1013. NoteStoreOpts = get_opt(note_store, Opts, []),
  1014. NoteStoreVerb = get_opt(verbosity, NoteStoreOpts, silence),
  1015. NoteStoreTimeout = get_opt(timeout, NoteStoreOpts, 30000),
  1016. ets:insert(snmpm_config_table, {note_store_verbosity, NoteStoreVerb}),
  1017. ets:insert(snmpm_config_table, {note_store_timeout, NoteStoreTimeout}),
  1018. %% -- Manager SNMP config --
  1019. ?vdebug("manager snmp config", []),
  1020. MgrConf = read_manager_config_file(ConfDir),
  1021. init_manager_config(MgrConf),
  1022. %% -- User config --
  1023. ?vdebug("users config", []),
  1024. Users = read_users_config_file(ConfDir),
  1025. init_users_config(Users),
  1026. %% -- Agents config --
  1027. ?vdebug("agents config", []),
  1028. Agents = read_agents_config_file(ConfDir),
  1029. init_agents_config(Agents),
  1030. %% -- USM config --
  1031. UsmUsers = read_usm_config_file(ConfDir),
  1032. init_usm_users_config(UsmUsers),
  1033. %% -- snmp engine init --
  1034. init_engine(),
  1035. ?vlog("started", []),
  1036. ok.
  1037. dets_open(Dir, DbInitError, Repair, AutoSave) ->
  1038. Name = ?CONFIG_DB,
  1039. Filename = dets_filename(Name, Dir),
  1040. case file:read_file_info(Filename) of
  1041. {ok, _} ->
  1042. %% File exists
  1043. case do_dets_open(Name, Filename, Repair, AutoSave) of
  1044. {ok, _Dets} ->
  1045. ok;
  1046. {error, Reason1} ->
  1047. info_msg("Corrupt local database: ~p", [Filename]),
  1048. case DbInitError of
  1049. terminate ->
  1050. error({failed_reopen_dets, Filename, Reason1});
  1051. _ ->
  1052. Saved = Filename ++ ".saved",
  1053. file:rename(Filename, Saved),
  1054. case do_dets_open(Name, Filename,
  1055. Repair, AutoSave) of
  1056. {ok, _Dets} ->
  1057. ok;
  1058. {error, Reason2} ->
  1059. error({failed_open_dets, Filename,
  1060. Reason1, Reason2})
  1061. end
  1062. end
  1063. end;
  1064. _ ->
  1065. case DbInitError of
  1066. create_db_and_dir ->
  1067. ok = filelib:ensure_dir(Filename);
  1068. _ ->
  1069. ok
  1070. end,
  1071. case do_dets_open(Name, Filename, Repair, AutoSave) of
  1072. {ok, _Dets} ->
  1073. ok;
  1074. {error, Reason} ->
  1075. error({failed_open_dets, Filename, Reason})
  1076. end
  1077. end.
  1078. do_dets_open(Name, Filename, Repair, AutoSave) ->
  1079. Opts = [{repair, Repair},
  1080. {auto_save, AutoSave},
  1081. {file, Filename}],
  1082. dets:open_file(Name, Opts).
  1083. dets_filename(Name, Dir) when is_atom(Name) ->
  1084. dets_filename(atom_to_list(Name), Dir);
  1085. dets_filename(Name, Dir) ->
  1086. filename:join(dets_filename1(Dir), Name).
  1087. dets_filename1([]) -> ".";
  1088. dets_filename1(Dir) -> Dir.
  1089. %% ------------------------------------------------------------------------
  1090. init_engine() ->
  1091. case get_engine_boots() of
  1092. {ok, Val} when Val < 2147483647 ->
  1093. set_engine_boots(Val + 1);
  1094. {ok, _} ->
  1095. ok;
  1096. _ ->
  1097. set_engine_boots(1)
  1098. end,
  1099. reset_engine_base().
  1100. reset_engine_base() ->
  1101. ets:insert(snmpm_config_table, {snmp_engine_base, snmp_misc:now(sec)}).
  1102. %% ------------------------------------------------------------------------
  1103. verify_options(Opts, Mandatory) ->
  1104. ?d("verify_options -> entry with"
  1105. "~n Opts: ~p"
  1106. "~n Mandatory: ~p", [Opts, Mandatory]),
  1107. verify_mandatory_options(Opts, Mandatory),
  1108. verify_options(Opts).
  1109. verify_options([]) ->
  1110. ?d("verify_options -> done", []),
  1111. ok;
  1112. verify_options([Opt|Opts]) ->
  1113. ?d("verify_options -> entry with"
  1114. "~n Opt: ~p", [Opt]),
  1115. verify_option(Opt),
  1116. verify_options(Opts).
  1117. verify_option({prio, Prio}) ->
  1118. verify_prio(Prio);
  1119. verify_option({mibs, Mibs}) ->
  1120. verify_mibs(Mibs);
  1121. verify_option({inform_request_behaviour, IRB}) ->
  1122. verify_irb(IRB);
  1123. verify_option({net_if, NetIfOpts}) ->
  1124. verify_net_if_opts(NetIfOpts);
  1125. verify_option({server, ServerOpts}) ->
  1126. verify_server_opts(ServerOpts);
  1127. verify_option({note_store, NoteStoreOpts}) ->
  1128. verify_note_store_opts(NoteStoreOpts);
  1129. verify_option({config, ConfOpts0}) ->
  1130. %% Make sure any db_dir option is first in the options list to make it
  1131. %% easier to check if the db_init_error option specifies that a missing
  1132. %% db_dir should be created.
  1133. ConfOpts = case lists:keytake(db_dir, 1, ConfOpts0) of
  1134. false -> ConfOpts0;
  1135. {value, Result, OtherOpts} -> [Result|OtherOpts]
  1136. end,
  1137. verify_config_opts(ConfOpts);
  1138. verify_option({versions, Vsns}) ->
  1139. verify_versions(Vsns);
  1140. verify_option({audit_trail_log, LogOpts}) ->
  1141. Mandatory = [dir, size],
  1142. case (catch verify_mandatory_options(LogOpts, Mandatory)) of
  1143. ok ->
  1144. verify_audit_trail_log_opts(LogOpts);
  1145. {error, {missing_mandatory, LogOpt}} ->
  1146. error({missing_mandatory, audit_trail_log, LogOpt})
  1147. end;
  1148. verify_option({def_user_mod, Mod}) ->
  1149. verify_module(def_user_mod, Mod);
  1150. verify_option({def_user_data, _Data}) ->
  1151. ok;
  1152. verify_option(Opt) ->
  1153. {error, {invalid_option, Opt}}.
  1154. verify_prio(Prio) when is_atom(Prio) ->
  1155. ok;
  1156. verify_prio(Prio) ->
  1157. error({invalid_prio, Prio}).
  1158. verify_irb(auto) ->
  1159. ok;
  1160. verify_irb(user) ->
  1161. ok;
  1162. verify_irb({user, To}) when is_integer(To) andalso (To > 0) ->
  1163. ok;
  1164. verify_irb(IRB) ->
  1165. error({invalid_irb, IRB}).
  1166. verify_mibs([]) ->
  1167. ok;
  1168. verify_mibs([Mib|Mibs]) when is_list(Mib) ->
  1169. verify_mibs(Mibs);
  1170. verify_mibs(Mibs) ->
  1171. error({invalid_mibs, Mibs}).
  1172. verify_config_opts([]) ->
  1173. ok;
  1174. verify_config_opts([{verbosity, Verbosity}|Opts]) ->
  1175. verify_verbosity(Verbosity),
  1176. verify_config_opts(Opts);
  1177. verify_config_opts([{dir, Dir}|Opts]) ->
  1178. verify_conf_dir(Dir),
  1179. verify_config_opts(Opts);
  1180. verify_config_opts([{db_dir, Dir}|Opts]) ->
  1181. case lists:keyfind(db_init_error, 1, Opts) of
  1182. {db_init_error, create_db_and_dir} ->
  1183. verify_conf_db_dir(Dir, false);
  1184. _ ->
  1185. verify_conf_db_dir(Dir, true)
  1186. end,
  1187. verify_config_opts(Opts);
  1188. verify_config_opts([{db_init_error, DbInitErr}|Opts]) ->
  1189. verify_conf_db_init_error(DbInitErr),
  1190. verify_config_opts(Opts);
  1191. verify_config_opts([{repair, Repair}|Opts]) ->
  1192. verify_conf_repair(Repair),
  1193. verify_config_opts(Opts);
  1194. verify_config_opts([{auto_save, AutoSave}|Opts]) ->
  1195. verify_conf_auto_save(AutoSave),
  1196. verify_config_opts(Opts);
  1197. verify_config_opts([Opt|_]) ->
  1198. error({invalid_config_option, Opt}).
  1199. verify_server_opts([]) ->
  1200. ok;
  1201. verify_server_opts([{verbosity, Verbosity}|Opts]) ->
  1202. verify_verbosity(Verbosity),
  1203. verify_server_opts(Opts);
  1204. verify_server_opts([{timeout, Timeout}|Opts]) ->
  1205. verify_server_timeout(Timeout),
  1206. verify_server_opts(Opts);
  1207. verify_server_opts([Opt|_]) ->
  1208. error({invalid_server_option, Opt}).
  1209. verify_server_timeout(T) when is_integer(T) andalso (T > 0) ->
  1210. ok;
  1211. verify_server_timeout(T) ->
  1212. error({invalid_server_timeout, T}).
  1213. verify_net_if_opts([]) ->
  1214. ok;
  1215. verify_net_if_opts([{module, Mod}|Opts]) ->
  1216. verify_network_interface_behaviour(Mod),
  1217. verify_net_if_opts(Opts);
  1218. verify_net_if_opts([{verbosity, Verbosity}|Opts]) ->
  1219. verify_verbosity(Verbosity),
  1220. verify_net_if_opts(Opts);
  1221. verify_net_if_opts([{options, Options}|Opts]) when is_list(Options) ->
  1222. verify_net_if_opts(Opts);
  1223. verify_net_if_opts([Opt|_]) ->
  1224. error({invalid_net_if_option, Opt}).
  1225. verify_network_interface_behaviour(Mod) ->
  1226. case snmp_misc:verify_behaviour(snmpm_network_interface, Mod) of
  1227. ok ->
  1228. ok;
  1229. Error ->
  1230. throw(Error)
  1231. end.
  1232. verify_note_store_opts([]) ->
  1233. ok;
  1234. verify_note_store_opts([{verbosity, Verbosity}|Opts]) ->
  1235. verify_verbosity(Verbosity),
  1236. verify_note_store_opts(Opts);
  1237. verify_note_store_opts([{timeout, Timeout}|Opts]) ->
  1238. verify_note_store_timeout(Timeout),
  1239. verify_note_store_opts(Opts);
  1240. verify_note_store_opts([Opt|_]) ->
  1241. error({invalid_note_store_option, Opt}).
  1242. verify_note_store_timeout(T) when is_integer(T) andalso (T > 0) ->
  1243. ok;
  1244. verify_note_store_timeout(T) ->
  1245. error({invalid_note_store_timeout, T}).
  1246. verify_conf_dir(Dir) ->
  1247. case (catch verify_dir(Dir)) of
  1248. ok ->
  1249. ok;
  1250. {error, Reason} ->
  1251. error({invalid_conf_dir, Dir, Reason});
  1252. _ ->
  1253. error({invalid_conf_dir, Dir})
  1254. end.
  1255. verify_conf_db_dir(Dir, true) ->
  1256. case (catch verify_dir(Dir)) of
  1257. ok ->
  1258. ok;
  1259. {error, Reason} ->
  1260. error({invalid_conf_db_dir, Dir, Reason});
  1261. _ ->
  1262. error({invalid_conf_db_dir, Dir})
  1263. end;
  1264. verify_conf_db_dir(_Dir, false) ->
  1265. ok.
  1266. verify_conf_db_init_error(terminate) ->
  1267. ok;
  1268. verify_conf_db_init_error(create) ->
  1269. ok;
  1270. verify_conf_db_init_error(create_db_and_dir) ->
  1271. ok;
  1272. verify_conf_db_init_error(InvalidDbInitError) ->
  1273. error({invalid_conf_db_init_error, InvalidDbInitError}).
  1274. verify_conf_repair(true) ->
  1275. ok;
  1276. verify_conf_repair(false) ->
  1277. ok;
  1278. verify_conf_repair(force) ->
  1279. ok;
  1280. verify_conf_repair(InvalidRepair) ->
  1281. error({invalid_conf_db_repair, InvalidRepair}).
  1282. verify_conf_auto_save(infinity) ->
  1283. ok;
  1284. verify_conf_auto_save(AutoSave)
  1285. when is_integer(AutoSave) andalso (AutoSave > 0) ->
  1286. ok;
  1287. verify_conf_auto_save(InvalidAutoSave) ->
  1288. error({invalid_conf_db_auto_save, InvalidAutoSave}).
  1289. verify_versions([]) ->
  1290. ok;
  1291. verify_versions([Vsn|Vsns]) ->
  1292. verify_version(Vsn),
  1293. verify_versions(Vsns);
  1294. verify_versions(Vsns) ->
  1295. error({invalid_versions, Vsns}).
  1296. verify_version(v1) ->
  1297. ok;
  1298. verify_version(v2) ->
  1299. ok;
  1300. verify_version(v3) ->
  1301. ok;
  1302. verify_version(Vsn) ->
  1303. error({invalid_version, Vsn}).
  1304. verify_audit_trail_log_opts([]) ->
  1305. ok;
  1306. verify_audit_trail_log_opts([{dir, Dir}|Opts]) ->
  1307. verify_log_dir(Dir),
  1308. verify_audit_trail_log_opts(Opts);
  1309. verify_audit_trail_log_opts([{type, Type}|Opts]) ->
  1310. verify_log_type(Type),
  1311. verify_audit_trail_log_opts(Opts);
  1312. verify_audit_trail_log_opts([{size, Size}|Opts]) ->
  1313. verify_log_size(Size),
  1314. verify_audit_trail_log_opts(Opts);
  1315. verify_audit_trail_log_opts([{repair, Repair}|Opts]) ->
  1316. verify_log_repair(Repair),
  1317. verify_audit_trail_log_opts(Opts);
  1318. verify_audit_trail_log_opts([{seqno, SeqNo}|Opts]) ->
  1319. verify_log_seqno(SeqNo),
  1320. verify_audit_trail_log_opts(Opts);
  1321. verify_audit_trail_log_opts([Opt|_Opts]) ->
  1322. error({invalid_audit_trail_log_option, Opt}).
  1323. verify_log_type(read) ->
  1324. ok;
  1325. verify_log_type(write) ->
  1326. ok;
  1327. verify_log_type(read_write) ->
  1328. ok;
  1329. verify_log_type(Type) ->
  1330. error({invalid_audit_trail_log_type, Type}).
  1331. verify_log_dir(Dir) ->
  1332. case (catch verify_dir(Dir)) of
  1333. ok ->
  1334. ok;
  1335. {error, Reason} ->
  1336. error({invalid_audit_trail_log_dir, Dir, Reason});
  1337. _ ->
  1338. error({invalid_audit_trail_log_dir, Dir})
  1339. end.
  1340. verify_log_size(Sz) when is_integer(Sz) andalso (Sz > 0) ->
  1341. ok;
  1342. verify_log_size(infinity) ->
  1343. ok;
  1344. verify_log_size({MaxNoBytes, MaxNoFiles})
  1345. when (is_integer(MaxNoBytes) andalso
  1346. (MaxNoBytes > 0) andalso
  1347. is_integer(MaxNoFiles) andalso
  1348. (MaxNoFiles > 0) andalso
  1349. (MaxNoFiles < 65000)) ->
  1350. ok;
  1351. verify_log_size(Sz) ->
  1352. error({invalid_audit_trail_log_size, Sz}).
  1353. verify_log_repair(true) -> ok;
  1354. verify_log_repair(false) -> ok;
  1355. verify_log_repair(truncate) -> ok;
  1356. verify_log_repair(Repair) ->
  1357. error({invalid_audit_trail_log_repair, Repair}).
  1358. verify_log_seqno(true) -> ok;
  1359. verify_log_seqno(false) -> ok;
  1360. verify_log_seqno(SeqNo) ->
  1361. error({invalid_audit_trail_log_seqno, SeqNo}).
  1362. verify_module(_, Mod) when is_atom(Mod) ->
  1363. ok;
  1364. verify_module(ReasonTag, Mod) ->
  1365. error({invalid_module, ReasonTag, Mod}).
  1366. % verify_bool(_, true) ->
  1367. % ok;
  1368. % verify_bool(_, false) ->
  1369. % ok;
  1370. % verify_bool(ReasonTag, Bool) ->
  1371. % error({invalid_bool, ReasonTag, Bool}).
  1372. verify_dir(Dir) when is_list(Dir) ->
  1373. case file:read_file_info(Dir) of
  1374. {ok, #file_info{type = directory}} ->
  1375. ok;
  1376. {ok, _} ->
  1377. {error, not_directory};
  1378. {error, _Reason} ->
  1379. {error, not_found}
  1380. end;
  1381. verify_dir(Dir) ->
  1382. {error, {invalid_log_dir, Dir}}.
  1383. verify_verbosity(Verbosity) ->
  1384. case snmp_verbosity:validate(Verbosity) of
  1385. Verbosity ->
  1386. ok;
  1387. _ ->
  1388. error({invalid_verbosity, Verbosity})
  1389. end.
  1390. %% mandatory() -> [mand()]
  1391. %% mand() -> atom() | {atom, [atom()]}
  1392. verify_mandatory_options(_Opts, []) ->
  1393. ok;
  1394. verify_mandatory_options(Opts, [Mand|Mands]) ->
  1395. verify_mandatory_option(Opts, Mand),
  1396. verify_mandatory_options(Opts, Mands).
  1397. verify_mandatory_option(Opts, {Mand, MandSubOpts}) ->
  1398. ?d("verify_mandatory_option -> entry with"
  1399. "~n Mand: ~p"
  1400. "~n MandSubObjs: ~p", [Mand, MandSubOpts]),
  1401. case lists:keysearch(Mand, 1, Opts) of
  1402. {value, {Mand, SubOpts}} ->
  1403. verify_mandatory_options(SubOpts, MandSubOpts);
  1404. false ->
  1405. ?d("missing mandatory option: ~w [~p]", [Mand, MandSubOpts]),
  1406. error({missing_mandatory, Mand, MandSubOpts})
  1407. end;
  1408. verify_mandatory_option(Opts, Mand) ->
  1409. ?d("verify_mandatory_option -> entry with"
  1410. "~n Mand: ~p", [Mand]),
  1411. case lists:keymember(Mand, 1, Opts) of
  1412. true ->
  1413. ok;
  1414. false ->
  1415. ?d("missing mandatory option: ~w", [Mand]),
  1416. error({missing_mandatory, Mand})
  1417. end.
  1418. %% ------------------------------------------------------------------------
  1419. init_manager_config([]) ->
  1420. ok;
  1421. init_manager_config([{Key, Val}|Confs]) ->
  1422. ets:insert(snmpm_config_table, {Key, Val}),
  1423. init_manager_config(Confs).
  1424. init_agent_default() ->
  1425. %% The purpose of the default_agent is only to have a place
  1426. %% to store system wide default values related to agents.
  1427. %%
  1428. AgentDefaultConfig =
  1429. [{port, ?DEFAULT_AGENT_PORT}, % Port
  1430. {timeout, 10000}, % Timeout
  1431. {max_message_size, 484}, % Max message (packet) size
  1432. {version, v2}, % MPModel
  1433. {sec_model, v2c}, % SecModel
  1434. {sec_name, "initial"}, % SecName
  1435. {sec_level, noAuthNoPriv}, % SecLevel
  1436. {community, "all-rights"}], % Community
  1437. do_update_agent_info(default_agent, AgentDefaultConfig).
  1438. read_agents_config_file(Dir) ->
  1439. Order = fun snmp_conf:no_order/2,
  1440. Check = fun check_agent_config/2,
  1441. try read_file(Dir, "agents.conf", Order, Check, [])
  1442. catch
  1443. throw:Error ->
  1444. ?vlog("agent config error: ~p", [Error]),
  1445. erlang:raise(throw, Error, erlang:get_stacktrace())
  1446. end.
  1447. check_agent_config(Agent, State) ->
  1448. {ok, {UserId, TargetName, Conf, Version}} = check_agent_config(Agent),
  1449. {ok, Vsns} = system_info(versions),
  1450. case lists:member(Version, Vsns) of
  1451. true ->
  1452. {{ok, {UserId, TargetName, Conf}}, State};
  1453. false ->
  1454. error({version_not_supported_by_manager, Version, Vsns})
  1455. end.
  1456. %% For backward compatibility
  1457. check_agent_config(
  1458. {UserId, TargetName, Community, Domain, Addr,
  1459. EngineId, Timeout, MaxMessageSize,
  1460. Version, SecModel, SecName, SecLevel}) when is_atom(Domain) ->
  1461. check_agent_config(
  1462. UserId, TargetName, Community, Domain, Addr,
  1463. EngineId, Timeout, MaxMessageSize,
  1464. Version, SecModel, SecName, SecLevel);
  1465. check_agent_config(
  1466. {UserId, TargetName, Community, Ip, Port,
  1467. EngineId, Timeout, MaxMessageSize,
  1468. Version, SecModel, SecName, SecLevel}) when is_integer(Port) ->
  1469. Domain = default_transport_domain(),
  1470. Addr = {Ip, Port},
  1471. check_agent_config(
  1472. UserId, TargetName, Community, Domain, Addr,
  1473. EngineId, Timeout, MaxMessageSize,
  1474. Version, SecModel, SecName, SecLevel);
  1475. check_agent_config(
  1476. {_UserId, _TargetName, _Community, Domain, Addr,
  1477. _EngineId, _Timeout, _MaxMessageSize,
  1478. _Version, _SecModel, _SecName, _SecLevel}) ->
  1479. error({bad_address, {Domain, Addr}});
  1480. check_agent_config(
  1481. {UserId, TargetName, Community, Domain, Ip, Port,
  1482. EngineId, Timeout, MaxMessageSize,
  1483. Version, SecModel, SecName, SecLevel}) ->
  1484. Addr = {Ip, Port},
  1485. check_agent_config(
  1486. UserId, TargetName, Community, Domain, Addr,
  1487. EngineId, Timeout, MaxMessageSize,
  1488. Version, SecModel, SecName, SecLevel);
  1489. check_agent_config(Agent) ->
  1490. error({bad_agent_config, Agent}).
  1491. check_agent_config(
  1492. UserId, TargetName, Comm, Domain, Addr,
  1493. EngineId, Timeout, MMS,
  1494. Version, SecModel, SecName, SecLevel) ->
  1495. ?vdebug("check_agent_config -> entry with"
  1496. "~n UserId: ~p"
  1497. "~n TargetName: ~p", [UserId, TargetName]),
  1498. snmp_conf:check_string(TargetName, {gt, 0}),
  1499. %% Note that the order of Conf *is* important.
  1500. %% Some properties may depend on others, so that
  1501. %% in order to verify one property, another must
  1502. %% be already verified (and present). An example
  1503. %% of this is the property 'taddress', for which
  1504. %% the property tdomain is needed.
  1505. Conf =
  1506. [{reg_type, target_name},
  1507. {tdomain,

Large files files are truncated, but you can click here to view the full file