1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-2020. 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-module(snmp). 21 22 23%%---------------------------------------------------------------------- 24%% This module contains the user interface to the snmp toolkit. 25%%---------------------------------------------------------------------- 26 27%% Application exports 28-export([start/0, start/1, stop/0, 29 start_agent/0, start_agent/1, 30 start_manager/0, start_manager/1, 31 config/0, 32 33 versions1/0, versions2/0, 34 print_versions/1, print_versions/2, 35 print_version_info/0, print_version_info/1, 36 37 date_and_time/0, 38 universal_time_to_date_and_time/1, 39 local_time_to_date_and_time_dst/1, 40 date_and_time_to_universal_time_dst/1, 41 validate_date_and_time/1, validate_date_and_time/2, 42 date_and_time_to_string/1, date_and_time_to_string/2, 43 date_and_time_to_string2/1, 44 45 str_apply/1, 46 47 sys_up_time/1, system_start_time/1, 48 49 passwd2localized_key/3, localize_key/3, 50 51 read_mib/1, 52 53 log_to_txt/5, log_to_txt/6, log_to_txt/7, log_to_txt/8, 54 log_to_io/4, log_to_io/5, log_to_io/6, log_to_io/7, 55 change_log_size/2, 56 57 octet_string_to_bits/1, bits_to_octet_string/1, 58 59 enable_trace/0, disable_trace/0, 60 set_trace/1, reset_trace/1, 61 set_trace/2, set_trace/3]). 62 63%% Compiler exports 64-export([c/1, c/2, is_consistent/1, mib_to_hrl/1, 65 compile/3]). 66 67%% Agent exports (Dont use these, they will be removed in OTP 24) 68-export([current_request_id/0, current_community/0, current_address/0, 69 current_context/0, current_net_if_data/0, 70 71 get_symbolic_store_db/0, 72 name_to_oid/1, name_to_oid/2, 73 oid_to_name/1, oid_to_name/2, 74 int_to_enum/2, int_to_enum/3, 75 enum_to_int/2, enum_to_int/3, 76 77 get/2, 78 info/1, 79 load_mibs/2, unload_mibs/2, dump_mibs/0, dump_mibs/1, 80 81 register_subagent/3, unregister_subagent/2, 82 83 send_notification/3, send_notification/4, send_notification/5, 84 send_notification/6, 85 send_trap/3, send_trap/4, 86 87 add_agent_caps/2, del_agent_caps/1, get_agent_caps/0, 88 89 log_to_txt/2, log_to_txt/3, log_to_txt/4, 90 change_log_size/1 91 92 ]). 93 94-export_type([ 95 dir/0, 96 snmp_timer/0, 97 98 atl_type/0, 99 verbosity/0, 100 101 engine_id/0, 102 tdomain/0, 103 community/0, 104 mms/0, 105 version/0, 106 sec_model/0, 107 sec_name/0, 108 sec_level/0, 109 110 oid/0, 111 varbind/0, 112 ivarbind/0, 113 asn1_type/0, 114 table_info/0, 115 variable_info/0, 116 me/0, 117 trap/0, 118 notification/0, 119 pdu/0, 120 trappdu/0, 121 mib/0, 122 mib_name/0, 123 124 error_status/0, 125 error_index/0, 126 127 void/0 128 ]). 129 130 131%% This is for XREF 132-deprecated( 133 [ 134 {c, 1, "use snmpc:compile/1 instead."}, 135 {c, 2, "use snmpc:compile/2 instead."}, 136 {compile, 3, "use snmpc:compile/3 instead."}, 137 {is_consistent, 1, "use snmpc:is_consistent/1 instead."}, 138 {mib_to_hrl, 1, "use snmpc:mib_to_hrl/1 instead."}, 139 140 {change_log_size, 1, "use snmpa:change_log_size/1 instead."}, 141 {log_to_txt, 2, "use snmpa:log_to_txt/2 instead."}, 142 {log_to_txt, 3, "use snmpa:log_to_txt/3 instead."}, 143 {log_to_txt, 4, "use snmpa:log_to_txt/4 instead."}, 144 145 {current_request_id, 0, "use snmpa:current_request_id/0 instead."}, 146 {current_community, 0, "use snmpa:current_community/0 instead."}, 147 {current_address, 0, "use snmpa:current_address/0 instead."}, 148 {current_context, 0, "use snmpa:current_context/0 instead."}, 149 {current_net_if_data, 0, "use snmpa:current_net_if_data/0 instead."}, 150 151 {get_symbolic_store_db, 0, "use snmpa:get_symbolic_store_db/0 instead."}, 152 {name_to_oid, 1, "use snmpa:name_to_oid/1 instead."}, 153 {name_to_oid, 2, "use snmpa:name_to_oid/2 instead."}, 154 {oid_to_name, 1, "use snmpa:oid_to_name/1 instead."}, 155 {oid_to_name, 2, "use snmpa:oid_to_name/2 instead."}, 156 {int_to_enum, 2, "use snmpa:int_to_enum/2 instead."}, 157 {int_to_enum, 3, "use snmpa:int_to_enum/3 instead."}, 158 {enum_to_int, 2, "use snmpa:enum_to_int/2 instead."}, 159 {enum_to_int, 3, "use snmpa:enum_to_int/3 instead."}, 160 161 {get, 2, "use snmpa:get/2 instead."}, 162 {info, 1, "use snmpa:info/1 instead."}, 163 {load_mibs, 2, "use snmpa:load_mibs/2 instead."}, 164 {unload_mibs, 2, "use snmpa:unload_mibs/2 instead."}, 165 {dump_mibs, 0, "use snmpa:dump_mibs/0 instead."}, 166 {dump_mibs, 1, "use snmpa:dump_mibs/1 instead."}, 167 168 {register_subagent, 3, "use snmpa:register_subagent/3 instead."}, 169 {unregister_subagent, 2, "use snmpa:unregister_subagent/2 instead."}, 170 171 {send_notification, 3, "use snmpa:send_notification/3 instead."}, 172 {send_notification, 4, "use snmpa:send_notification/4 instead."}, 173 {send_notification, 5, "use snmpa:send_notification/5 instead."}, 174 {send_notification, 6, "use snmpa:send_notification/6 instead."}, 175 {send_trap, 3, "use snmpa:send_trap/3 instead."}, 176 {send_trap, 4, "use snmpa:send_trap/4 instead."}, 177 178 {add_agent_caps, 2, "use snmpa:add_agent_caps/2 instead."}, 179 {del_agent_caps, 1, "use snmpa:del_agent_caps/1 instead."}, 180 {get_agent_caps, 0, "use snmpa:get_agent_caps/0 instead."} 181 ]). 182 183 184-define(APPLICATION, snmp). 185-define(ATL_BLOCK_DEFAULT, true). 186 187-include_lib("snmp/include/snmp_types.hrl"). 188 189 190%%----------------------------------------------------------------- 191%% Types 192%%----------------------------------------------------------------- 193 194-type dir() :: string(). 195-type snmp_timer() :: #snmp_incr_timer{}. 196 197-type atl_type() :: read | write | read_write. 198-type verbosity() :: info | log | debug | trace | silence. 199 200-type engine_id() :: string(). 201-type tdomain() :: transportDomainUdpIpv4 | transportDomainUdpIpv6. 202-type community() :: string(). 203-type mms() :: non_neg_integer(). 204-type version() :: v1 | v2 | v3. 205-type sec_model() :: any | v1 | v2c | usm. 206-type sec_name() :: string(). 207-type sec_level() :: noAuthNoPriv | authNoPriv | authPriv. 208 209-type oid() :: [non_neg_integer()]. 210-type varbind() :: #varbind{}. 211-type ivarbind() :: #ivarbind{}. 212-type asn1_type() :: #asn1_type{}. 213-type table_info() :: #table_info{}. 214-type variable_info() :: #variable_info{}. 215-type me() :: #me{}. 216-type trap() :: #trap{}. 217-type notification() :: #notification{}. 218-type mib() :: #mib{}. 219-type mib_name() :: string(). 220-type pdu() :: #pdu{}. 221-type trappdu() :: #trappdu{}. 222 223%% We should really specify all of these, but they are so numerous... 224%% See the validate_err/1 function in the snmpa_agent. 225%% Here are a number of them: 226%% badValue | 227%% commitFailed | 228%% genErr | 229%% inconsistentName | inconsistentValue | 230%% noAccess | noCreation | 231%% noSuchInstance | noSuchName | noSuchObject | 232%% notWritable | 233%% resourceUnavailable | 234%% undoFailed | 235%% wrongValue 236 237-type error_status() :: atom(). 238-type error_index() :: pos_integer(). 239 240-type void() :: term(). 241 242 243%%----------------------------------------------------------------- 244%% Application 245%%----------------------------------------------------------------- 246 247start() -> 248 application:start(?APPLICATION). 249 250stop() -> 251 application:stop(?APPLICATION). 252 253start(p) -> 254 start(permanent); 255start(tr) -> 256 start(transient); 257start(te) -> 258 start(temporary); 259start(Type) -> 260 application:start(?APPLICATION, Type). 261 262 263start_agent() -> 264 snmp_app:start_agent(). 265 266start_agent(Type) -> 267 snmp_app:start_agent(Type). 268 269start_manager() -> 270 snmp_app:start_manager(). 271 272start_manager(Type) -> 273 snmp_app:start_manager(Type). 274 275 276config() -> snmp_config:config(). 277 278 279%%----------------------------------------------------------------- 280 281enable_trace() -> 282 HandleSpec = {fun handle_trace_event/2, dummy}, 283 dbg:tracer(process, HandleSpec). 284 285disable_trace() -> 286 dbg:stop(). 287 288set_trace(Module) when is_atom(Module) -> 289 set_trace([Module]); 290set_trace(Modules) when is_list(Modules) -> 291 Opts = [], % Use default values for all options 292 set_trace(Modules, Opts). 293 294reset_trace(Module) when is_atom(Module) -> 295 set_trace(Module, disable); 296reset_trace(Modules) when is_list(Modules) -> 297 set_trace(Modules, disable). 298 299set_trace(Module, disable) when is_atom(Module) -> 300 dbg:ctp(Module); 301set_trace(Module, Opts) when is_atom(Module) andalso is_list(Opts) -> 302 (catch set_trace(all, Module, Opts)); 303set_trace(Modules, Opts) when is_list(Modules) -> 304 (catch set_trace(all, Modules, Opts)). 305 306set_trace(Item, Module, Opts) when is_atom(Module) -> 307 set_trace(Item, [{Module, []}], Opts); 308set_trace(_Item, Modules, disable) when is_list(Modules) -> 309 DisableTrace = 310 fun(Module) when is_atom(Module) -> 311 dbg:ctp(Module); 312 (_) -> 313 ok 314 end, 315 lists:foreach(DisableTrace, Modules); 316set_trace(Item, Modules, Opts) when is_list(Modules) -> 317 Mods = parse_modules(Modules, Opts), 318 SetTrace = 319 fun({Module, ModOpts}) -> 320 set_module_trace(Module, ModOpts) 321 end, 322 lists:foreach(SetTrace, Mods), 323 Flags = 324 case lists:keysearch(timestamp, 1, Opts) of 325 {value, {timestamp, false}} -> 326 [call]; 327 _ -> 328 [call, timestamp] 329 end, 330 case dbg:p(Item, Flags) of 331 {ok, _} -> 332 ok; 333 Error -> 334 Error 335 end. 336 337set_module_trace(Module, disable) -> 338 dbg:ctp(Module); 339set_module_trace(Module, Opts) -> 340 ReturnTrace = 341 case lists:keysearch(return_trace, 1, Opts) of 342 {value, {return_trace, false}} -> 343 []; 344 _ -> 345 %% Default is allways to include return values 346 [{return_trace}] 347 end, 348 TraceRes = 349 case lists:keysearch(scope, 1, Opts) of 350 {value, {scope, all_functions}} -> 351 dbg:tpl(Module, [{'_', [], ReturnTrace}]); 352 {value, {scope, exported_functions}} -> 353 dbg:tp(Module, [{'_', [], ReturnTrace}]); 354 {value, {scope, Func}} when is_atom(Func) -> 355 dbg:tpl(Module, Func, [{'_', [], ReturnTrace}]); 356 {value, {scope, {Func, Arity}}} when is_atom(Func) andalso 357 is_integer(Arity) -> 358 dbg:tpl(Module, Func, Arity, [{'_', [], ReturnTrace}]); 359 false -> 360 %% Default scope is exported functions 361 dbg:tp(Module, [{'_', [], ReturnTrace}]) 362 end, 363 case TraceRes of 364 {error, Reason} -> 365 throw({error, {failed_enabling_trace, Module, Opts, Reason}}); 366 _ -> 367 ok 368 end. 369 370 371parse_modules(Modules, Opts) -> 372 parse_modules(Modules, Opts, []). 373 374parse_modules([], _Opts, Acc) -> 375 lists:reverse(Acc); 376 377parse_modules([Module|Modules], Opts, Acc) 378 when is_atom(Module) andalso is_list(Opts) -> 379 parse_modules(Modules, Opts, [{Module, Opts}|Acc]); 380 381parse_modules([{Module, ModOpts}|Modules], Opts, Acc) 382 when is_atom(Module) andalso is_list(ModOpts) andalso is_list(Opts) -> 383 NewModOpts = update_trace_options(Opts, ModOpts), 384 parse_modules(Modules, Opts, [{Module, NewModOpts}|Acc]); 385 386parse_modules([_|Modules], Opts, Acc) -> 387 parse_modules(Modules, Opts, Acc). 388 389 390update_trace_options([], Opts) -> 391 Opts; 392update_trace_options([{Key, _} = Opt|Opts], ModOpts) -> 393 case lists:keysearch(Key, 1, ModOpts) of 394 {value, _} -> 395 update_trace_options(Opts, ModOpts); 396 _ -> 397 update_trace_options(Opts, [Opt|ModOpts]) 398 end; 399update_trace_options([_|Opts], ModOpts) -> 400 update_trace_options(Opts, ModOpts). 401 402 403handle_trace_event({trace, Who, call, Event}, Data) -> 404 io:format("*** call trace event *** " 405 "~n Who: ~p" 406 "~n Event: ~p" 407 "~n", [Who, Event]), 408 Data; 409handle_trace_event({trace, Who, return_from, Func, Value}, Data) -> 410 io:format("*** return trace event *** " 411 "~n Who: ~p" 412 "~n Function: ~p" 413 "~n Value: ~p" 414 "~n", [Who, Func, Value]), 415 Data; 416handle_trace_event({trace_ts, Who, call, {Mod, Func, Args}, Ts}, Data) 417 when is_atom(Mod) andalso is_atom(Func) andalso is_list(Args) -> 418 io:format("*** call trace event ~s *** " 419 "~n Who: ~p" 420 "~n Mod: ~p" 421 "~n Func: ~p" 422 "~n Args: ~p" 423 "~n", [format_timestamp(Ts), Who, Mod, Func, Args]), 424 Data; 425handle_trace_event({trace_ts, Who, call, Event, Ts}, Data) -> 426 io:format("*** call trace event ~s *** " 427 "~n Who: ~p" 428 "~n Event: ~p" 429 "~n", [format_timestamp(Ts), Who, Event]), 430 Data; 431handle_trace_event({trace_ts, Who, return_from, {Mod, Func, Arity}, Value, Ts}, 432 Data) 433 when is_atom(Mod) andalso is_atom(Func) andalso is_integer(Arity) -> 434 io:format("*** return trace event ~s *** " 435 "~n Who: ~p" 436 "~n Mod: ~p" 437 "~n Func: ~p" 438 "~n Arity: ~p" 439 "~n Value: ~p" 440 "~n", [format_timestamp(Ts), Who, Mod, Func, Arity, Value]), 441 Data; 442handle_trace_event({trace_ts, Who, return_from, Func, Value, Ts}, Data) -> 443 io:format("*** return trace event ~s *** " 444 "~n Who: ~p" 445 "~n Function: ~p" 446 "~n Value: ~p" 447 "~n", [format_timestamp(Ts), Who, Func, Value]), 448 Data; 449handle_trace_event(TraceEvent, Data) -> 450 io:format("*** trace event *** " 451 "~n TraceEvent: ~p" 452 "~n", [TraceEvent]), 453 Data. 454 455format_timestamp({_N1, _N2, N3} = Now) -> 456 {Date, Time} = calendar:now_to_datetime(Now), 457 {YYYY,MM,DD} = Date, 458 {Hour,Min,Sec} = Time, 459 FormatDate = 460 io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", 461 [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), 462 lists:flatten(FormatDate). 463 464 465%%----------------------------------------------------------------- 466%% {ok, Vs} = snmp:versions1(), snmp:print_versions(Vs). 467 468print_version_info() -> 469 {ok, Vs} = versions1(), 470 print_versions(Vs). 471 472print_version_info(Prefix) -> 473 {ok, Vs} = versions1(), 474 print_versions(Prefix, Vs). 475 476print_versions(Versions) -> 477 print_versions("", Versions). 478 479print_versions(Prefix, Versions) 480 when is_list(Prefix) andalso is_list(Versions) -> 481 do_print_versions(Prefix, Versions); 482print_versions(Prefix, Versions) 483 when (is_integer(Prefix) andalso (Prefix >= 0)) andalso is_list(Versions) -> 484 do_print_versions(lists:duplicate(Prefix, $ ), Versions); 485print_versions(Prefix, BadVersions) 486 when is_list(Prefix) orelse (is_integer(Prefix) andalso (Prefix >= 0)) -> 487 {error, {bad_versions, BadVersions}}; 488print_versions(Prefix, BadVersions) 489 when is_list(BadVersions) -> 490 {error, {bad_prefix, Prefix}}; 491print_versions(Prefix, BadVersions) -> 492 {error, {bad_args, Prefix, BadVersions}}. 493 494do_print_versions(Prefix, Versions) -> 495 print_sys_info(Prefix, Versions), 496 print_os_info(Prefix, Versions), 497 print_mods_info(Prefix, Versions). 498 499print_sys_info(Prefix, Versions) -> 500 case key1search(sys_info, Versions) of 501 {value, SysInfo} when is_list(SysInfo) -> 502 {value, Arch} = key1search(arch, SysInfo, "Not found"), 503 {value, Ver} = key1search(ver, SysInfo, "Not found"), 504 io:format("~sSystem info: " 505 "~n~s Arch: ~s" 506 "~n~s Ver: ~s" 507 "~n", [Prefix, 508 Prefix, Arch, 509 Prefix, Ver]), 510 ok; 511 _ -> 512 io:format("System info: Not found~n", []), 513 not_found 514 end. 515 516print_os_info(Prefix, Versions) -> 517 case key1search(os_info, Versions) of 518 {value, OsInfo} when is_list(OsInfo) -> 519 Fam = 520 case key1search(fam, OsInfo, "Not found") of 521 {value, F} when is_atom(F) -> 522 atom_to_list(F); 523 {value, LF} when is_list(LF) -> 524 LF; 525 {value, XF} -> 526 lists:flatten(io_lib:format("~p", [XF])) 527 end, 528 Name = 529 case key1search(name, OsInfo) of 530 {value, N} when is_atom(N) -> 531 "[" ++ atom_to_list(N) ++ "]"; 532 {value, LN} when is_list(LN) -> 533 "[" ++ LN ++ "]"; 534 not_found -> 535 "" 536 end, 537 Ver = 538 case key1search(ver, OsInfo, "Not found") of 539 {value, T} when is_tuple(T) -> 540 tversion(T); 541 {value, LV} when is_list(LV) -> 542 LV; 543 {value, XV} -> 544 lists:flatten(io_lib:format("~p", [XV])) 545 end, 546 io:format("~sOS info: " 547 "~n~s Family: ~s ~s" 548 "~n~s Ver: ~s" 549 "~n", [Prefix, 550 Prefix, Fam, Name, 551 Prefix, Ver]), 552 ok; 553 _ -> 554 io:format("~sOS info: Not found~n", [Prefix]), 555 not_found 556 end. 557 558tversion(T) -> 559 L = tuple_to_list(T), 560 lversion(L). 561 562lversion([]) -> 563 ""; 564lversion([A]) -> 565 integer_to_list(A); 566lversion([A|R]) -> 567 integer_to_list(A) ++ "." ++ lversion(R). 568 569print_mods_info(Prefix, Versions) -> 570 case key1search(mod_info, Versions) of 571 {value, ModsInfo} when is_list(ModsInfo) -> 572 io:format("~sModule info: ~n", [Prefix]), 573 F = fun(MI) -> print_mod_info(Prefix, MI) end, 574 lists:foreach(F, ModsInfo); 575 _ -> 576 io:format("~sModule info: Not found~n", [Prefix]), 577 not_found 578 end. 579 580print_mod_info(Prefix, {Module, Info}) -> 581 Vsn = 582 case key1search(vsn, Info) of 583 {value, I} when is_integer(I) -> 584 integer_to_list(I); 585 _ -> 586 "Not found" 587 end, 588 AppVsn = 589 case key1search(app_vsn, Info) of 590 {value, S1} when is_list(S1) -> 591 S1; 592 _ -> 593 "Not found" 594 end, 595 CompVer = 596 case key1search(compiler_version, Info) of 597 {value, S2} when is_list(S2) -> 598 S2; 599 _ -> 600 "Not found" 601 end, 602 Digest = 603 case key1search(md5, Info) of 604 {value, MD5} when is_binary(MD5) -> 605 [io_lib:format("~2.16.0b", [Byte]) || <<Byte>> <= MD5]; 606 _ -> 607 "Not found" 608 end, 609 io:format("~s ~w:~n" 610 "~s Vsn: ~s~n" 611 "~s App vsn: ~s~n" 612 "~s Compiler ver: ~s~n" 613 "~s MD5 digest: ~s~n", 614 [Prefix, Module, 615 Prefix, Vsn, 616 Prefix, AppVsn, 617 Prefix, CompVer, 618 Prefix, Digest]), 619 ok. 620 621key1search(Key, Vals) -> 622 case lists:keysearch(Key, 1, Vals) of 623 {value, {Key, Val}} -> 624 {value, Val}; 625 false -> 626 not_found 627 end. 628 629key1search(Key, Vals, Def) -> 630 case key1search(Key, Vals) of 631 not_found -> 632 {value, Def}; 633 Value -> 634 Value 635 end. 636 637 638%%----------------------------------------------------------------- 639 640versions1() -> 641 case ms1() of 642 {ok, Mods} -> 643 {ok, version_info(Mods)}; 644 Error -> 645 Error 646 end. 647 648versions2() -> 649 case ms2() of 650 {ok, Mods} -> 651 {ok, version_info(Mods)}; 652 Error -> 653 Error 654 end. 655 656version_info(Mods) -> 657 SysInfo = sys_info(), 658 OsInfo = os_info(), 659 ModInfo = [mod_version_info(Mod) || Mod <- Mods], 660 [{sys_info, SysInfo}, {os_info, OsInfo}, {mod_info, ModInfo}]. 661 662mod_version_info(Mod) -> 663 Info = Mod:module_info(), 664 {Mod, 665 case key1search(attributes, Info) of 666 {value, Attr} -> 667 case key1search(vsn, Attr) of 668 {value, [Vsn]} -> 669 [{vsn, Vsn}]; 670 not_found -> 671 [] 672 end ++ 673 case key1search(app_vsn, Attr) of 674 {value, AppVsn} -> 675 [{app_vsn, AppVsn}]; 676 not_found -> 677 [] 678 end; 679 not_found -> 680 [] 681 end ++ 682 case key1search(compile, Info) of 683 {value, Comp} -> 684 case key1search(version, Comp) of 685 {value, Ver} -> 686 [{compiler_version, Ver}]; 687 not_found -> 688 [] 689 end ++ 690 case key1search(time, Comp) of 691 {value, Ver} -> 692 [{compile_time, Ver}]; 693 not_found -> 694 [] 695 end; 696 not_found -> 697 [] 698 end ++ 699 case key1search(md5, Info) of 700 {value, Bin} -> 701 [{md5, Bin}]; 702 not_found -> 703 [] 704 end}. 705 706sys_info() -> 707 SysArch = string:strip(erlang:system_info(system_architecture),right,$\n), 708 SysVer = string:strip(erlang:system_info(system_version),right,$\n), 709 [{arch, SysArch}, {ver, SysVer}]. 710 711os_info() -> 712 {OsFam, OsName} = os:type(), 713 [{fam, OsFam}, {name, OsName}, {ver, os:version()}]. 714 715ms1() -> 716 App = ?APPLICATION, 717 LibDir = code:lib_dir(App), 718 File = filename:join([LibDir, "ebin", atom_to_list(App) ++ ".app"]), 719 case file:consult(File) of 720 {ok, [{application, App, AppFile}]} -> 721 case lists:keysearch(modules, 1, AppFile) of 722 {value, {modules, Mods}} -> 723 {ok, Mods}; 724 _ -> 725 {error, {invalid_format, modules}} 726 end; 727 Error -> 728 {error, {invalid_format, Error}} 729 end. 730 731ms2() -> 732 application:get_key(?APPLICATION, modules). 733 734 735%%----------------------------------------------------------------- 736%% Returns: current time as a DateAndTime type (defined in rfc1903) 737%%----------------------------------------------------------------- 738date_and_time() -> 739 UTC = calendar:universal_time(), 740 Local = calendar:universal_time_to_local_time(UTC), 741 date_and_time(Local, UTC). 742 743date_and_time(Local, UTC) -> 744 DiffSecs = calendar:datetime_to_gregorian_seconds(Local) - 745 calendar:datetime_to_gregorian_seconds(UTC), 746 short_time(Local) ++ diff(DiffSecs). 747 748short_time({{Y,M,D},{H,Mi,S}}) -> 749 [y1(Y), y2(Y), M, D, H, Mi, S, 0]. 750 751%% This function will only be called if there has been some 752%% validation error, and as it is strict, it allways returns 753%% false. 754strict_validation(_What, _Data) -> 755 false. 756 757kiribati_validation(diff, Diff) -> 758 check_kiribati_diff(Diff); 759kiribati_validation(_What, _Data) -> 760 false. 761 762check_kiribati_diff([$+, H, M]) 763 when ((0 =< H) andalso (H < 14) andalso (0 =< M) andalso (M < 60)) orelse 764 ((H =:= 14) andalso (M =:= 0)) -> 765 true; 766check_kiribati_diff([$-, H, M]) 767 when ((0 =< H) andalso (H < 14) andalso (0 =< M) andalso (M < 60)) orelse 768 ((H =:= 14) andalso (M =:= 0)) -> 769 true; 770check_kiribati_diff(_) -> 771 false. 772 773 774date_and_time_to_string2(DAT) -> 775 Validate = fun(What, Data) -> kiribati_validation(What, Data) end, 776 date_and_time_to_string(DAT, Validate). 777 778date_and_time_to_string(DAT) -> 779 Validate = fun(What, Data) -> strict_validation(What, Data) end, 780 date_and_time_to_string(DAT, Validate). 781date_and_time_to_string(DAT, Validate) when is_function(Validate) -> 782 case validate_date_and_time(DAT, Validate) of 783 true -> 784 dat2str(DAT); 785 false -> 786 exit({badarg, {?MODULE, date_and_time_to_string, [DAT]}}) 787 end. 788 789dat2str([Y1,Y2, Mo, D, H, M, S, Ds | Diff]) -> 790 lists:flatten(io_lib:format("~w-~w-~w,~w:~w:~w.~w", 791 [y(Y1,Y2),Mo,D,H,M,S,Ds]) ++ 792 case Diff of 793 [Sign,Hd,Md] -> 794 io_lib:format(",~c~w:~w", 795 [Sign,Hd,Md]); 796 _ -> [] 797 end). 798 799 800y1(Y) -> (Y bsr 8) band 255. 801y2(Y) -> Y band 255. 802 803y(Y1, Y2) -> 256 * Y1 + Y2. 804 805diff(Secs) -> 806 case calendar:seconds_to_daystime(Secs) of 807 {0, {H, M,_}} -> 808 [$+, H, M]; 809 {-1, _} -> 810 {0, {H, M, _}} = calendar:seconds_to_daystime(-Secs), 811 [$-, H, M] 812 end. 813 814universal_time_to_date_and_time(UTC) -> 815 short_time(UTC) ++ [$+, 0, 0]. 816 817local_time_to_date_and_time_dst(Local) -> 818 case calendar:local_time_to_universal_time_dst(Local) of 819 [] -> 820 []; 821 [UTC] -> 822 [date_and_time(Local, UTC)]; 823 [UTC1, UTC2] -> 824 [date_and_time(Local, UTC1), date_and_time(Local, UTC2)] 825 end. 826 827date_and_time_to_universal_time_dst([Y1, Y2, Mo, D, H, M, S, _Ds]) -> 828 %% Local time specified, convert to UTC 829 Local = {{y(Y1,Y2), Mo, D}, {H, M, S}}, 830 calendar:local_time_to_universal_time_dst(Local); 831date_and_time_to_universal_time_dst([Y1, Y2, Mo, D, H, M, S, _Ds, Sign, Hd, Md]) -> 832 %% Time specified as local time + diff from UTC. Conv to UTC. 833 Local = {{y(Y1,Y2), Mo, D}, {H, M, S}}, 834 LocalSecs = calendar:datetime_to_gregorian_seconds(Local), 835 Diff = (Hd*60 + Md)*60, 836 UTCSecs = if Sign == $+ -> LocalSecs - Diff; 837 Sign == $- -> LocalSecs + Diff 838 end, 839 [calendar:gregorian_seconds_to_datetime(UTCSecs)]. 840 841 842validate_date_and_time(DateAndTime) -> 843 Validate = fun(What, Data) -> strict_validation(What, Data) end, 844 validate_date_and_time(DateAndTime, Validate). 845 846validate_date_and_time(DateAndTime, Validate) when is_function(Validate) -> 847 do_validate_date_and_time(DateAndTime, Validate). 848 849do_validate_date_and_time([Y1,Y2, Mo, D, H, M, S, Ds | Diff], Validate) 850 when ((0 =< Y1) andalso (0 =< Y2)) andalso 851 ((0 < Mo) andalso (Mo < 13)) andalso 852 ((0 < D) andalso (D < 32) andalso (0 =< H)) andalso 853 (H < 24) andalso 854 ((0 =< M) andalso (M < 60)) andalso 855 ((0 =< S) andalso (S < 61)) andalso 856 ((0 =< Ds) andalso (Ds < 10)) -> 857 case check_diff(Diff, Validate) of 858 true -> 859 Year = y(Y1,Y2), 860 case calendar:valid_date(Year, Mo, D) of 861 true -> 862 true; 863 _ -> 864 Validate(valid_date, {Year, Mo, D}) 865 end; 866 false -> 867 false 868 end; 869do_validate_date_and_time([Y1,Y2, Mo, D, H, M, S, Ds | Diff], Validate) -> 870 Valid = 871 Validate(year, {Y1, Y2}) andalso 872 Validate(month, Mo) andalso 873 Validate(day, D) andalso 874 Validate(hour, H) andalso 875 Validate(minute, M) andalso 876 Validate(seconds, S) andalso 877 Validate(deci_seconds, Ds), 878 if 879 Valid =:= true -> 880 case check_diff(Diff, Validate) of 881 true -> 882 Year = y(Y1,Y2), 883 case calendar:valid_date(Year, Mo, D) of 884 true -> 885 true; 886 _ -> 887 Validate(valid_date, {Year, Mo, D}) 888 end; 889 false -> 890 false 891 end; 892 true -> 893 false 894 end; 895do_validate_date_and_time(_, _) -> 896 false. 897 898%% OTP-4206 (now according to RFC-2579) 899check_diff([], _) -> 900 true; 901check_diff([$+, H, M], _) 902 when (0 =< H) andalso (H < 14) andalso (0 =< M) andalso (M < 60) -> 903 true; 904check_diff([$-, H, M], _) 905 when (0 =< H) andalso (H < 14) andalso (0 =< M) andalso (M < 60) -> 906 true; 907check_diff(Diff, Validate) -> 908 Validate(diff, Diff). 909 910 911%%----------------------------------------------------------------- 912%% System start- and up-time 913%%----------------------------------------------------------------- 914 915system_start_time(agent) -> 916 snmpa:system_start_time(); 917system_start_time(manager) -> 918 snmpm:system_start_time(). 919 920sys_up_time(agent) -> 921 snmpa:sys_up_time(); 922sys_up_time(manager) -> 923 snmpm:sys_up_time(). 924 925 926 927%%----------------------------------------------------------------- 928%% Utility functions for OCTET-STRING / BITS conversion. 929%%----------------------------------------------------------------- 930 931octet_string_to_bits(S) -> 932 snmp_pdus:octet_str_to_bits(S). 933 934bits_to_octet_string(B) -> 935 snmp_pdus:bits_to_str(B). 936 937 938%%%----------------------------------------------------------------- 939%%% USM functions 940%%%----------------------------------------------------------------- 941 942passwd2localized_key(Alg, Passwd, EngineID) -> 943 snmp_usm:passwd2localized_key(Alg, Passwd, EngineID). 944 945localize_key(Alg, Key, EngineID) -> 946 snmp_usm:localize_key(Alg, Key, EngineID). 947 948 949%%%----------------------------------------------------------------- 950%%% Read a mib 951%%%----------------------------------------------------------------- 952 953read_mib(FileName) -> 954 snmp_misc:read_mib(FileName). 955 956 957%%%----------------------------------------------------------------- 958%%% Audit Trail Log functions 959%%%----------------------------------------------------------------- 960 961log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile) -> 962 Block = ?ATL_BLOCK_DEFAULT, 963 Start = null, 964 Stop = null, 965 log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop). 966 967log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block) 968 when ((Block =:= true) orelse (Block =:= false)) -> 969 Start = null, 970 Stop = null, 971 log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop); 972log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start) -> 973 Block = ?ATL_BLOCK_DEFAULT, 974 Stop = null, 975 log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop). 976 977log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start) 978 when ((Block =:= true) orelse (Block =:= false)) -> 979 Stop = null, 980 log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop); 981log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> 982 Block = ?ATL_BLOCK_DEFAULT, 983 log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop). 984 985log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Block, Start, Stop) -> 986 snmp_log:log_to_txt(LogName, Block, LogFile, LogDir, Mibs, OutFile, 987 Start, Stop). 988 989 990log_to_io(LogDir, Mibs, LogName, LogFile) -> 991 Block = ?ATL_BLOCK_DEFAULT, 992 Start = null, 993 Stop = null, 994 log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop). 995 996log_to_io(LogDir, Mibs, LogName, LogFile, Block) 997 when ((Block =:= true) orelse (Block =:= false)) -> 998 Start = null, 999 Stop = null, 1000 log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop); 1001log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> 1002 Block = ?ATL_BLOCK_DEFAULT, 1003 Stop = null, 1004 log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop). 1005 1006log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start) 1007 when ((Block =:= true) orelse (Block =:= false)) -> 1008 Stop = null, 1009 log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop); 1010log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> 1011 Block = ?ATL_BLOCK_DEFAULT, 1012 log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop). 1013 1014log_to_io(LogDir, Mibs, LogName, LogFile, Block, Start, Stop) -> 1015 snmp_log:log_to_io(LogName, Block, LogFile, LogDir, Mibs, Start, Stop). 1016 1017change_log_size(LogName, NewSize) -> 1018 snmp_log:change_size(LogName, NewSize). 1019 1020 1021%%%----------------------------------------------------------------- 1022%%% Misc 1023%%%----------------------------------------------------------------- 1024 1025%% Usage: erl -s snmp str_apply '{Mod,Func,ArgList}' 1026str_apply([Atom]) -> 1027 Str = atom_to_list(Atom), 1028 {Mod, Func, Args} = to_erlang_term(Str), 1029 apply(Mod, Func, Args). 1030 1031to_erlang_term(String) -> 1032 {ok, Tokens, _} = erl_scan:string(lists:append([String, ". "])), 1033 {ok, Term} = erl_parse:parse_term(Tokens), 1034 Term. 1035 1036 1037%%%----------------------------------------------------------------- 1038%%% BACKWARD COMPATIBILLITY CRAP 1039%%%----------------------------------------------------------------- 1040 1041c(File) -> snmpc:compile(File). 1042c(File, Options) -> snmpc:compile(File, Options). 1043 1044is_consistent(Filenames) -> 1045 snmpc:is_consistent(Filenames). 1046 1047mib_to_hrl(MibName) -> 1048 snmpc:mib_to_hrl(MibName). 1049 1050compile(Input, Output, Options) -> 1051 snmpc:compile(Input, Output, Options). 1052 1053get_symbolic_store_db() -> snmpa:get_symbolic_store_db(). 1054 1055name_to_oid(Name) -> snmpa:name_to_oid(Name). 1056name_to_oid(Db, Name) -> snmpa:name_to_oid(Db, Name). 1057oid_to_name(OID) -> snmpa:oid_to_name(OID). 1058oid_to_name(Db, OID) -> snmpa:oid_to_name(Db, OID). 1059enum_to_int(Name, Enum) -> snmpa:enum_to_int(Name, Enum). 1060enum_to_int(Db, Name, Enum) -> snmpa:enum_to_int(Db, Name, Enum). 1061int_to_enum(Name, Int) -> snmpa:int_to_enum(Name, Int). 1062int_to_enum(Db, Name, Int) -> snmpa:int_to_enum(Db, Name, Int). 1063 1064current_request_id() -> snmpa:current_request_id(). 1065current_context() -> snmpa:current_context(). 1066current_community() -> snmpa:current_community(). 1067current_address() -> snmpa:current_address(). 1068current_net_if_data() -> snmpa:current_net_if_data(). 1069 1070get(Agent, Vars) -> snmpa:get(Agent, Vars). 1071info(Agent) -> snmpa:info(Agent). 1072dump_mibs() -> snmpa:dump_mibs(). 1073dump_mibs(File) -> snmpa:dump_mibs(File). 1074load_mibs(Agent, Mibs) -> snmpa:load_mibs(Agent, Mibs). 1075unload_mibs(Agent, Mibs) -> snmpa:unload_mibs(Agent, Mibs). 1076send_notification(Agent, Notification, Recv) -> 1077 snmpa:send_notification(Agent, Notification, Recv). 1078send_notification(Agent, Notification, Recv, Varbinds) -> 1079 snmpa:send_notification(Agent, Notification, Recv, Varbinds). 1080send_notification(Agent, Notification, Recv, NotifyName, Varbinds) -> 1081 snmpa:send_notification(Agent, Notification, Recv, NotifyName, Varbinds). 1082send_notification(Agent, Notification, Recv, NotifyName, 1083 ContextName, Varbinds) -> 1084 snmpa:send_notification(Agent, Notification, Recv, NotifyName, 1085 ContextName, Varbinds). 1086send_trap(Agent, Trap, Community) -> 1087 snmpa:send_trap(Agent, Trap, Community). 1088send_trap(Agent, Trap, Community, Varbinds) -> 1089 snmpa:send_trap(Agent, Trap, Community, Varbinds). 1090register_subagent(Agent, SubTree, SubAgent) -> 1091 snmpa:register_subagent(Agent, SubTree, SubAgent). 1092unregister_subagent(Agent, SubOidOrPid) -> 1093 snmpa:unregister_subagent(Agent, SubOidOrPid). 1094 1095add_agent_caps(Oid, Descr) -> snmpa:add_agent_caps(Oid, Descr). 1096del_agent_caps(Index) -> snmpa:del_agent_caps(Index). 1097get_agent_caps() -> snmpa:get_agent_caps(). 1098 1099log_to_txt(LogDir, Mibs) -> 1100 snmpa:log_to_txt(LogDir, Mibs). 1101log_to_txt(LogDir, Mibs, OutFile) -> 1102 snmpa:log_to_txt(LogDir, Mibs, OutFile). 1103log_to_txt(LogDir, Mibs, OutFile, LogName) -> 1104 snmpa:log_to_txt(LogDir, Mibs, OutFile, LogName). 1105change_log_size(NewSize) -> 1106 snmpa:change_log_size(NewSize). 1107 1108 1109 1110