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