1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2014-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%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21%% This test suite uses the following external programs: 22%% snmpget From packet 'snmp' (in Ubuntu 12.04) 23%% snmpd From packet 'snmpd' (in Ubuntu 12.04) 24%% snmptrapd From packet 'snmpd' (in Ubuntu 12.04) 25%% They originate from the Net-SNMP applications, see: 26%% http://net-snmp.sourceforge.net/ 27 28 29-module(snmp_to_snmpnet_SUITE). 30 31-export([ 32 suite/0, all/0, groups/0, 33 init_per_suite/1, end_per_suite/1, 34 init_per_group/2, end_per_group/2, 35 init_per_testcase/2, end_per_testcase/2, 36 37 erlang_agent_netsnmp_get/0, erlang_agent_netsnmp_get/1, 38 erlang_agent_netsnmp_inform/0, erlang_agent_netsnmp_inform/1, 39 erlang_manager_netsnmp_get/0, erlang_manager_netsnmp_get/1 40 41 ]). 42 43-include("snmp_test_lib.hrl"). 44-include_lib("common_test/include/ct.hrl"). 45-include_lib("snmp/include/STANDARD-MIB.hrl"). 46 47-define(AGENT_ENGINE_ID, "ErlangSnmpAgent"). 48-define(MANAGER_ENGINE_ID, "ErlangSnmpManager"). 49-define(AGENT_PORT, 4000). 50-define(MANAGER_PORT, 8989). 51-define(DEFAULT_MAX_MESSAGE_SIZE, 484). 52 53expected(?sysDescr_instance = Oid, get) -> 54 OidStr = oid_str(Oid), 55 iolist_to_binary([OidStr | " = STRING: \"Erlang SNMP agent\""]). 56 57 58%%-------------------------------------------------------------------- 59%% Common Test interface functions ----------------------------------- 60%%-------------------------------------------------------------------- 61 62suite() -> [{ct_hooks,[ts_install_cth]}]. 63 64all() -> 65 [ 66 {group, ipv4}, 67 {group, ipv6}, 68 {group, ipv4_ipv6} 69 ]. 70 71groups() -> 72 [ 73 {ipv4, [], ipv4_cases()}, 74 {ipv6, [], ipv6_cases()}, 75 {ipv4_ipv6, [], ipv4_ipv6_cases()}, 76 77 {snmpget, [], snmpget_cases()}, 78 {snmptrapd, [], snmptrapd_cases()}, 79 {snmpd_mt, [], snmpd_mt_cases()}, 80 {snmpd, [], snmpd_cases()} 81 ]. 82 83ipv4_cases() -> 84 [ 85 {group, snmpget}, 86 {group, snmptrapd}, 87 {group, snmpd_mt}, 88 {group, snmpd} 89 ]. 90 91ipv6_cases() -> 92 [ 93 {group, snmpget}, 94 {group, snmptrapd}, 95 {group, snmpd_mt}, 96 {group, snmpd} 97 ]. 98 99ipv4_ipv6_cases() -> 100 [ 101 {group, snmpget}, 102 {group, snmptrapd}, 103 {group, snmpd_mt}, 104 {group, snmpd} 105 ]. 106 107snmpget_cases() -> 108 [ 109 erlang_agent_netsnmp_get 110 ]. 111 112snmptrapd_cases() -> 113 [ 114 erlang_agent_netsnmp_inform 115 ]. 116 117snmpd_mt_cases() -> 118 [ 119 erlang_manager_netsnmp_get 120 ]. 121 122snmpd_cases() -> 123 [ 124 erlang_manager_netsnmp_get 125 ]. 126 127 128 129%% 130%% ----- 131%% 132 133init_per_suite(Config0) -> 134 ?IPRINT("init_per_suite -> entry with" 135 "~n Config: ~p", [Config0]), 136 137 case netsnmp_init(Config0) of 138 {skip, _} = SKIP -> 139 SKIP; 140 141 Config1 -> 142 case ?LIB:init_per_suite(Config1) of 143 {skip, _} = SKIP -> 144 SKIP; 145 146 Config2 when is_list(Config2) -> 147 snmp_test_sys_monitor:start(), 148 149 ?IPRINT("init_per_suite -> end when" 150 "~n Config: ~p", [Config2]), 151 152 Config2 153 end 154 end. 155 156netsnmp_init(Config) -> 157 case has_netsnmp() of 158 true -> 159 case proper_netsnmp_version() of 160 true -> 161 [{agent_port, ?AGENT_PORT}, 162 {manager_port, ?MANAGER_PORT} | Config]; 163 false -> 164 {skip, "Buggy NetSNMP"} 165 end; 166 false -> 167 {skip, "No NetSNMP"} 168 end. 169 170has_netsnmp() -> 171 netsnmp_check("NET-SNMP"). 172 173proper_netsnmp_version() -> 174 not netsnmp_check("5.4|5.6.2.1"). 175 176netsnmp_check(RE) -> 177 case re:run(os:cmd("snmpd -v"), RE, [{capture, first}]) of 178 nomatch -> 179 false; 180 {match, _} -> 181 true 182 end. 183 184 185end_per_suite(Config) -> 186 ?IPRINT("end_per_suite -> entry with" 187 "~n Config: ~p", [Config]), 188 189 snmp_test_sys_monitor:stop(), 190 ?LIB:end_per_suite(Config), 191 192 ?IPRINT("end_per_suite -> end"), 193 194 Config. 195 196%% 197%% ----- 198%% 199 200init_per_group(ipv4, Config) -> 201 init_per_group_ip([inet], Config); 202init_per_group(ipv6, Config) -> 203 init_per_group_ipv6([inet6], Config); 204init_per_group(ipv4_ipv6, Config) -> 205 init_per_group_ipv6([inet, inet6], Config); 206 207init_per_group(snmpget = Exec, Config) -> 208 %% From Ubuntu package snmp 209 init_per_group_agent(Exec, Config); 210init_per_group(snmptrapd = Exec, Config) -> 211 %% From Ubuntu package snmpd 212 init_per_group_agent(Exec, Config); 213init_per_group(snmpd_mt, Config) -> 214 %% From Ubuntu package snmp 215 init_per_group_manager( 216 snmpd, 217 [{manager_net_if_module, snmpm_net_if_mt} | Config]); 218init_per_group(snmpd = Exec, Config) -> 219 %% From Ubuntu package snmp 220 init_per_group_manager( 221 Exec, 222 [{manager_net_if_module, snmpm_net_if} | Config]); 223 224init_per_group(_, Config) -> 225 Config. 226 227init_per_group_ipv6(Families, Config) -> 228 case ?HAS_SUPPORT_IPV6() of 229 true -> 230 init_per_group_ip(Families, Config); 231 false -> 232 {skip, "Host does not support IPv6"} 233 end. 234 235init_per_group_ip(Families, Config) -> 236 AgentPort = ?config(agent_port, Config), 237 ManagerPort = ?config(manager_port, Config), 238 Transports = 239 [begin 240 Addr = ?LIB:localhost(Family), 241 {domain(Family), {Addr, AgentPort}} 242 end || Family <- Families], 243 Targets = 244 [begin 245 Addr = ?LIB:localhost(Family), 246 {domain(Family), {Addr, ManagerPort}} 247 end || Family <- Families], 248 [{transports, Transports}, {targets, Targets} | Config]. 249 250init_per_group_agent(Exec, Config) -> 251 Versions = [v2], 252 Dir = ?config(priv_dir, Config), 253 Transports = ?config(transports, Config), 254 Targets = ?config(targets, Config), 255 agent_config(Dir, Transports, Targets, Versions), 256 find_executable(Exec, [{snmp_versions, Versions} | Config]). 257 258init_per_group_manager(Exec, Config) -> 259 Versions = [v2], 260 Dir = ?config(priv_dir, Config), 261 Targets = ?config(targets, Config), 262 manager_config(Dir, Targets), 263 find_executable(Exec, [{snmp_versions, Versions} | Config]). 264 265 266end_per_group(_GroupName, Config) -> 267 Config. 268 269 270 271%% 272%% ----- 273%% 274 275init_per_testcase(_Case, Config) -> 276 ?IPRINT("init_per_testcase -> entry with" 277 "~n Config: ~p", [Config]), 278 279 snmp_test_global_sys_monitor:reset_events(), 280 281 Dog = ct:timetrap(?SECS(20)), 282 application:stop(snmp), 283 application:unload(snmp), 284 Config1 = [{watchdog, Dog} | Config], 285 286 ?IPRINT("init_per_testcase -> done when" 287 "~n Config: ~p", [Config1]), 288 289 Config1. 290 291end_per_testcase(_, Config) -> 292 293 ?IPRINT("end_per_testcase -> entry with" 294 "~n Config: ~p", [Config]), 295 296 ?IPRINT("system events during test: " 297 "~n ~p", [snmp_test_global_sys_monitor:events()]), 298 299 case application:stop(snmp) of 300 ok -> 301 ok; 302 E1 -> 303 ct:pal("application:stop(snmp) -> ~p", [E1]) 304 end, 305 case application:unload(snmp) of 306 ok -> 307 ok; 308 E2 -> 309 ct:pal("application:unload(snmp) -> ~p", [E2]) 310 end, 311 312 ?IPRINT("end_per_testcase -> done with" 313 "~n Config: ~p", [Config]), 314 315 Config. 316 317find_executable(Exec, Config) -> 318 ExecStr = atom_to_list(Exec), 319 case os:find_executable(ExecStr) of 320 false -> 321 %% The sbin dirs are not in the PATH on all platforms... 322 find_sys_executable( 323 Exec, ExecStr, 324 [["usr", "local", "sbin"], 325 ["usr", "sbin"], 326 ["sbin"]], 327 Config); 328 Path -> 329 [{Exec, Path} | Config] 330 end. 331 332find_sys_executable(_Exec, ExecStr, [], _Config) -> 333 {skip, ExecStr ++ " not found"}; 334find_sys_executable(Exec, ExecStr, [Dir | Dirs], Config) -> 335 case os:find_executable(filename:join(["/" | Dir] ++ [ExecStr])) of 336 false -> 337 find_sys_executable(Exec, ExecStr, Dirs, Config); 338 Path -> 339 [{Exec, Path} | Config] 340 end. 341 342start_agent(Config) -> 343 ok = application:load(snmp), 344 ok = application:set_env(snmp, agent, agent_app_env(Config)), 345 ok = application:start(snmp). 346 347start_manager(Config) -> 348 ok = application:load(snmp), 349 ok = application:set_env(snmp, manager, manager_app_env(Config)), 350 ok = application:start(snmp). 351 352 353 354%%-------------------------------------------------------------------- 355%% Test Cases -------------------------------------------------------- 356%%-------------------------------------------------------------------- 357erlang_agent_netsnmp_get() -> 358 [{doc,"Test that we can access erlang snmp agent " 359 "from snmpnet manager"}]. 360 361erlang_agent_netsnmp_get(Config) when is_list(Config) -> 362 Transports = ?config(transports, Config), 363 start_agent(Config), 364 Oid = ?sysDescr_instance, 365 Expected = expected(Oid, get), 366 try 367 begin 368 [Expected = snmpget(Oid, Transport, Config) 369 || Transport <- Transports], 370 ok 371 end 372 catch 373 throw:{skip, _} = SKIP -> 374 SKIP 375 end. 376 377 378%%-------------------------------------------------------------------- 379erlang_manager_netsnmp_get() -> 380 [{doc,"Test that the erlang snmp manager can access snmpnet agent"}]. 381 382erlang_manager_netsnmp_get(Config) when is_list(Config) -> 383 Community = "happy-testing", 384 SysDescr = "Net-SNMP agent", 385 TargetName = "Target Net-SNMP agent", 386 Transports = ?config(transports, Config), 387 case start_snmpd(Community, SysDescr, Config) of 388 {skip, _} = SKIP -> 389 SKIP; 390 ProgHandle -> 391 start_manager(Config), 392 snmp_manager_user:start_link(self(), test_user), 393 [snmp_manager_user:register_agent( 394 TargetName++domain_suffix(Domain), 395 [{reg_type, target_name}, 396 {tdomain, Domain}, {taddress, Addr}, 397 {community, Community}, {engine_id, "EngineId"}, 398 {version, v2}, {sec_model, v2c}, {sec_level, noAuthNoPriv}]) 399 || {Domain, Addr} <- Transports], 400 Results = 401 [snmp_manager_user:sync_get( 402 TargetName++domain_suffix(Domain), 403 [?sysDescr_instance]) 404 || {Domain, _} <- Transports], 405 ct:pal("sync_get -> ~p", [Results]), 406 snmp_manager_user:stop(), 407 stop_program(ProgHandle), 408 [{ok, 409 {noError, 0, 410 [{varbind, ?sysDescr_instance, 'OCTET STRING', SysDescr,1}] }, 411 _} = R || R <- Results], 412 ok 413 end. 414 415 416%%-------------------------------------------------------------------- 417erlang_agent_netsnmp_inform() -> 418 [{doc, "TBD"}]. 419 420erlang_agent_netsnmp_inform(Config) when is_list(Config) -> 421 DataDir = ?config(data_dir, Config), 422 Mib = "TestTrapv2", 423 424 start_agent(Config), 425 ok = snmpa:load_mib(snmp_master_agent, filename:join(DataDir, Mib)), 426 427 case start_snmptrapd(Mib, Config) of 428 {skip, _} = SKIP -> 429 SKIP; 430 ProgHandle -> 431 snmpa:send_notification( 432 snmp_master_agent, testTrapv22, {erlang_agent_test, self()}), 433 receive 434 {snmp_targets, erlang_agent_test, Addresses} -> 435 ct:pal("Notification sent to: ~p~n", [Addresses]), 436 erlang_agent_netsnmp_inform_responses(Addresses) 437 end, 438 stop_program(ProgHandle) 439 end. 440 441erlang_agent_netsnmp_inform_responses([]) -> 442 receive 443 {snmp_notification, erlang_agent_test, _} = Unexpected -> 444 ct:pal("Unexpected response: ~p", [Unexpected]), 445 erlang_agent_netsnmp_inform_responses([]) 446 after 0 -> 447 ok 448 end; 449erlang_agent_netsnmp_inform_responses([Address | Addresses]) -> 450 receive 451 {snmp_notification, erlang_agent_test, 452 {got_response, Address}} -> 453 ct:pal("Got response from: ~p~n", [Address]), 454 erlang_agent_netsnmp_inform_responses(Addresses); 455 {snmp_notification, erlang_agent_test, 456 {no_response, _} = NoResponse} -> 457 ct:fail(NoResponse) 458 end. 459 460%%-------------------------------------------------------------------- 461%% Internal functions ------------------------------------------------ 462%%-------------------------------------------------------------------- 463 464snmpget(Oid, Transport, Config) -> 465 Versions = ?config(snmp_versions, Config), 466 467 Args = 468 ["-c", "public", net_snmp_version(Versions), 469 "-m", ":", 470 "-Cf", 471 net_snmp_addr_str(Transport), 472 oid_str(Oid)], 473 case start_program(snmpget, Args, none, Config) of 474 {skip, _} = SKIP -> 475 throw(SKIP); 476 ProgHandle -> 477 {_, line, Line} = get_program_output(ProgHandle), 478 stop_program(ProgHandle), 479 Line 480 end. 481 482start_snmptrapd(Mibs, Config) -> 483 DataDir = ?config(data_dir, Config), 484 MibDir = filename:join(code:lib_dir(snmp), "mibs"), 485 Targets = ?config(targets, Config), 486 SnmptrapdArgs = 487 ["-f", "-Lo", "-C", 488 "-m", Mibs, 489 "-M", MibDir++":"++DataDir, 490 "--disableAuthorization=yes", 491 "--snmpTrapdAddr=" ++ net_snmp_addr_str(Targets)], 492 {ok, StartCheckMP} = re:compile("NET-SNMP version ", [anchored]), 493 start_program(snmptrapd, SnmptrapdArgs, StartCheckMP, Config). 494 495start_snmpd(Community, SysDescr, Config) -> 496 DataDir = ?config(data_dir, Config), 497 Targets = ?config(targets, Config), 498 Transports = ?config(transports, Config), 499 Port = mk_port_number(), 500 CommunityArgs = 501 ["--rocommunity"++domain_suffix(Domain)++"=" 502 ++Community++" "++inet_parse:ntoa(Ip) 503 || {Domain, {Ip, _}} <- Targets], 504 505 SnmpdArgs = 506 ["-f", "-r", %"-Dverbose", 507 "-c", filename:join(DataDir, "snmpd.conf"), 508 "-C", 509 "-Lo", 510 "-m", ":", 511 "--sysDescr="++SysDescr, 512 "--agentXSocket=tcp:localhost:"++integer_to_list(Port)] 513 ++ CommunityArgs 514 ++ [net_snmp_addr_str(Transports)], 515 {ok, StartCheckMP} = re:compile("NET-SNMP version ", [anchored]), 516 start_program(snmpd, SnmpdArgs, StartCheckMP, Config). 517 518start_program(Prog, Args, StartCheckMP, Config) -> 519 ct:pal("Starting program: ~w ~p", [Prog, Args]), 520 Path = ?config(Prog, Config), 521 DataDir = ?config(data_dir, Config), 522 StartWrapper = filename:join(DataDir, "start_stop_wrapper"), 523 Parent = self(), 524 %% process_flag(trap_exit, true), 525 {Pid, Mon} = 526 spawn_monitor( 527 fun () -> 528 run_program(Parent, StartWrapper, [Path | Args]) 529 end), 530 start_check(Pid, Mon, StartCheckMP). 531 532start_check(Pid, Mon, none) -> 533 {Pid, Mon}; 534start_check(Pid, Mon, StartCheckMP) -> 535 receive 536 {Pid, line, Line} -> 537 case re:run(Line, StartCheckMP, [{capture, none}]) of 538 match -> 539 {Pid, Mon}; 540 nomatch -> 541 start_check(Pid, Mon, StartCheckMP) 542 end; 543 {'DOWN', Mon, _, _Pid, {skip, Reason} = SKIP} -> 544 ct:pal("Received DOWN from ~p" 545 "~n Skip Reason: ~p", [_Pid, Reason]), 546 SKIP; 547 {'DOWN', Mon, _, _, Reason} -> 548 ct:fail("Prog ~p start failed: ~p", [Pid, Reason]) 549 end. 550 551get_program_output({Pid, Mon}) -> 552 receive 553 {Pid, _, _} = Msg -> 554 Msg; 555 {'DOWN', Mon, _, _, Reason} -> 556 ct:fail("Prog ~p crashed: ~p", [Pid, Reason]) 557 end. 558 559stop_program({Pid, _} = Handle) -> 560 Pid ! {self(), stop}, 561 wait_program_stop(Handle). 562 563wait_program_stop({Pid, Mon}) -> 564 receive 565 {Pid, exit, ExitStatus} -> 566 receive 567 {'DOWN', Mon, _, _, _} -> 568 ExitStatus 569 end; 570 {'DOWN', Mon, _, _, Reason} -> 571 ct:fail("Prog stop: ~p", [Reason]) 572 end. 573 574run_program(Parent, StartWrapper, ProgAndArgs) -> 575 [Prog | _] = ProgAndArgs, 576 Port = 577 open_port( 578 {spawn_executable, StartWrapper}, 579 [{args, ProgAndArgs}, binary, stderr_to_stdout, {line, 80}, 580 exit_status]), 581 ct:pal("Prog ~p started: ~p", [Port, Prog]), 582 run_program_loop(Parent, Port, []). 583 584run_program_loop(Parent, Port, Buf) -> 585 receive 586 {Parent, stop} -> 587 true = port_command(Port, <<"stop\n">>), 588 ct:pal("Prog ~p stop", [Port]), 589 run_program_loop(Parent, Port, Buf); 590 {Port, {data, {Flag, Data}}} -> 591 case Flag of 592 eol -> 593 Line = iolist_to_binary(lists:reverse(Buf, Data)), 594 ct:pal("Prog ~p output: ~s", [Port, Line]), 595 %% There are potentially many different fail outputs, 596 %% but for now we test for just this one: illegal option 597 IOpt = "illegal option", 598 case string:find(binary_to_list(Line), IOpt) of 599 nomatch -> 600 Parent ! {self(), line, Line}, 601 run_program_loop(Parent, Port, []); 602 Line2 -> 603 %% Try to extract the actual illegal option string 604 IOpt2 = 605 case string:take( 606 string:prefix(Line2, IOpt), [$-, $ ]) of 607 {_, Str} when length(Str) > 0 -> 608 Str; 609 _X -> 610 Line2 611 end, 612 ct:pal("Force program ~p stop", [Port]), 613 true = port_command(Port, <<"stop\n">>), 614 (catch port_close(Port)), 615 exit({skip, {illegal_option, IOpt2}}) 616 end; 617 noeol -> 618 run_program_loop(Parent, Port, [Data | Buf]) 619 end; 620 {Port, {exit_status, ExitStatus}} -> 621 ct:pal("Prog ~p exit: ~p", [Port, ExitStatus]), 622 catch port_close(Port), 623 Parent ! {self(), exit, ExitStatus}; 624 Unexpected -> 625 ct:pal("run_program_loop Unexpected: ~p", [Unexpected]), 626 run_program_loop(Parent, Port, Buf) 627 end. 628 629 630agent_app_env(Config) -> 631 Dir = ?config(priv_dir, Config), 632 Vsns = ?config(snmp_versions, Config), 633 [{versions, Vsns}, 634 {agent_type, master}, 635 {agent_verbosity, trace}, 636 {db_dir, Dir}, 637 {audit_trail_log, [{type, read_write}, 638 {dir, Dir}, 639 {size, {10240, 10}}]}, 640 {config, [{dir, Dir}, 641 {force_load, true}, 642 {verbosity, trace}]}, 643 {local_db, [{repair, true}, 644 {verbosity, silence}]}, 645 {mib_server, [{verbosity, silence}]}, 646 {symbolic_store, [{verbosity, silence}]}, 647 {note_store, [{verbosity, silence}]}, 648 {net_if, [{verbosity, trace}]}]. 649 650manager_app_env(Config) -> 651 Dir = ?config(priv_dir, Config), 652 Vsns = ?config(snmp_versions, Config), 653 NetIfModule = ?config(manager_net_if_module, Config), 654 [{versions, Vsns}, 655 {audit_trail_log, [{type, read_write}, 656 {dir, Dir}, 657 {size, {10240, 10}}]}, 658 {net_if, [{module, NetIfModule}]}, 659 {config, [{dir, Dir}, 660 {db_dir, Dir}, 661 {verbosity, trace}]} 662 ]. 663 664oid_str([1 | Ints]) -> 665 "iso." ++ oid_str_tl(Ints); 666oid_str(Ints) -> 667 oid_str_tl(Ints). 668 669oid_str_tl([]) -> 670 ""; 671oid_str_tl([Int]) -> 672 integer_to_list(Int); 673oid_str_tl([Int | Ints]) -> 674 integer_to_list(Int) ++ "." ++ oid_str_tl(Ints). 675 676agent_config(Dir, Transports, Targets, Versions) -> 677 EngineID = ?AGENT_ENGINE_ID, 678 MMS = ?DEFAULT_MAX_MESSAGE_SIZE, 679 ok = snmp_config:write_agent_snmp_conf(Dir, Transports, EngineID, MMS), 680 ok = snmp_config:write_agent_snmp_context_conf(Dir), 681 ok = snmp_config:write_agent_snmp_community_conf(Dir), 682 ok = 683 snmp_config:write_agent_snmp_standard_conf( 684 Dir, "snmp_to_snmpnet_SUITE"), 685 ok = 686 snmp_config:write_agent_snmp_target_addr_conf( 687 Dir, Targets, Versions), 688 ok = snmp_config:write_agent_snmp_target_params_conf(Dir, Versions), 689 ok = snmp_config:write_agent_snmp_notify_conf(Dir, inform), 690 ok = snmp_config:write_agent_snmp_vacm_conf(Dir, Versions, none). 691 692manager_config(Dir, Targets) -> 693 EngineID = ?MANAGER_ENGINE_ID, 694 MMS = ?DEFAULT_MAX_MESSAGE_SIZE, 695 ok = snmp_config:write_manager_snmp_conf(Dir, Targets, MMS, EngineID). 696 697net_snmp_version([v3 | _]) -> 698 "-v3"; 699net_snmp_version([v2 | _]) -> 700 "-v2c"; 701net_snmp_version([v1 | _]) -> 702 "-v1". 703 704domain(inet) -> 705 transportDomainUdpIpv4; 706domain(inet6) -> 707 transportDomainUdpIpv6. 708 709net_snmp_addr_str([Target | Targets]) -> 710 net_snmp_addr_str(Target) ++ 711 case Targets of 712 [] -> 713 []; 714 [_ | _] -> 715 "," ++ net_snmp_addr_str(Targets) 716 end; 717net_snmp_addr_str({transportDomainUdpIpv4, {Addr, Port}}) -> 718 "udp:" ++ 719 inet_parse:ntoa(Addr) ++ ":" ++ 720 integer_to_list(Port); 721net_snmp_addr_str({transportDomainUdpIpv6, {Addr, Port}}) -> 722 "udp6:[" ++ 723 inet_parse:ntoa(Addr) ++ "]:" ++ 724 integer_to_list(Port). 725 726domain_suffix(transportDomainUdpIpv4) -> 727 ""; 728domain_suffix(transportDomainUdpIpv6) -> 729 "6". 730 731mk_port_number() -> 732 {ok, Socket} = gen_udp:open(0, [{reuseaddr, true}]), 733 {ok, PortNum} = inet:port(Socket), 734 ok = gen_udp:close(Socket), 735 PortNum. 736 737