1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1996-2021. 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-module(snmp_test_mgr). 22 23 24%%---------------------------------------------------------------------- 25%% This module implements a simple SNMP manager for Erlang. Its used 26%% during by the agent test suite. 27%%---------------------------------------------------------------------- 28 29%% c(snmp_test_mgr). 30%% snmp_test_mgr:start(). 31%% snmp_test_mgr:g([[sysContact,0]]). 32 33%% snmp_test_mgr:start([{engine_id, "mbjk's engine"}, v3, {agent, "clip"}, {mibs, ["../mibs/SNMPv2-MIB"]}]). 34 35%% snmp_test_mgr:start([{engine_id, "agentEngine"}, {user, "iwl_test"}, {dir, "mgr_conf"}, {sec_level, authPriv}, v3, {agent, "clip"}]). 36 37%% User interface 38-export([start_link/1, start/1, stop/0, 39 d/0, discovery/0, 40 g/1, s/1, gn/1, gn/0, r/0, gb/3, rpl/1, 41 send_bytes/1, 42 expect/2,expect/3,expect/4,expect/6,get_response/2, 43 receive_response/0, 44 purify_oid/1, 45 oid_to_name/1, name_to_oid/1]). 46 47%% Internal exports 48-export([get_oid_from_varbind/1, 49 var_and_value_to_varbind/2, flatten_oid/2, make_vb/1]). 50-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]). 51 52-include_lib("snmp/include/snmp_types.hrl"). 53-include_lib("snmp/include/STANDARD-MIB.hrl"). 54-include("snmp_test_lib.hrl"). 55-include_lib("snmp/src/app/snmp_internal.hrl"). 56 57-record(state, {dbg = true, 58 quiet, 59 parent, 60 timeout = 3500, 61 print_traps = true, 62 mini_mib, 63 packet_server, 64 last_sent_pdu, 65 last_received_pdu}). 66 67-define(SERVER, ?MODULE). 68-define(PACK_SERV, snmp_test_mgr_misc). 69 70start_link(Options) -> 71 gen_server:start_link({local, ?SERVER}, ?MODULE, {Options, self()}, []). 72 73start(Options) -> 74 gen_server:start({local, ?SERVER}, ?MODULE, {Options, self()}, []). 75 76stop() -> 77 call(stop). 78 79d() -> 80 discovery(). 81 82discovery() -> 83 call(discovery). 84 85g(Oids) -> 86 cast({get, Oids}). 87 88%% VarsAndValues is: {PlainOid, o|s|i, Value} (unknown mibs) | {Oid, Value} 89s(VarsAndValues) -> 90 cast({set, VarsAndValues}). 91 92gn(Oids) when is_list(Oids) -> 93 cast({get_next, Oids}); 94gn(N) when is_integer(N) -> 95 cast({iter_get_next, N}). 96gn() -> 97 cast(iter_get_next). 98 99r() -> 100 cast(resend_pdu). 101 102gb(NonRepeaters, MaxRepetitions, Oids) -> 103 cast({bulk, {NonRepeaters, MaxRepetitions, Oids}}). 104 105rpl(RespPdu) -> 106 cast({response, RespPdu}). 107 108send_bytes(Bytes) -> 109 cast({send_bytes, Bytes}). 110 111purify_oid(Oid) -> 112 call({purify_oid, Oid}, 5000). 113 114oid_to_name(Oid) -> 115 call({oid_to_name, Oid}, 5000). 116 117name_to_oid(Name) -> 118 call({name_to_oid, Name}, 5000). 119 120 121%%---------------------------------------------------------------------- 122%% Purpose: For writing test sequences 123%% Args: Y=any (varbinds) | trap | timeout | VarBinds | ErrStatus 124%% Returns: ok|{error, Id, Reason} 125%%---------------------------------------------------------------------- 126expect(Id,Y) -> echo_errors(expect_impl(Id,Y)). 127expect(Id,v2trap,VBs) -> echo_errors(expect_impl(Id,v2trap,VBs)); 128expect(Id,report,VBs) -> echo_errors(expect_impl(Id,report,VBs)); 129expect(Id,{inform, Reply},VBs) -> 130 echo_errors(expect_impl(Id,{inform,Reply},VBs)). 131expect(Id,Err,Idx,VBs) -> echo_errors(expect_impl(Id,Err,Idx,VBs)). 132expect(Id,trap, Enterp, Generic, Specific, ExpectedVarbinds) -> 133 echo_errors(expect_impl(Id,trap,Enterp,Generic, 134 Specific,ExpectedVarbinds)). 135 136%%----------------------------------------------------------------- 137%% Purpose: For writing test sequences 138%%----------------------------------------------------------------- 139get_response(Id, Vars) -> echo_errors(get_response_impl(Id, Vars)). 140 141%%---------------------------------------------------------------------- 142%% Receives a response from the agent. 143%% Returns: a PDU or {error, Reason}. 144%% It doesn't receive traps though. 145%%---------------------------------------------------------------------- 146receive_response() -> 147 receive_response(get_timeout()). 148 149receive_response(Timeout) -> 150 d("await response within ~w ms",[Timeout]), 151 receive 152 {snmp_pdu, PDU} when is_record(PDU, pdu) -> 153 d("received PDU: ~n\t~p",[PDU]), 154 PDU 155 after Timeout -> 156 d("response timeout",[]), 157 {error, timeout} 158 end. 159 160 161get_timeout() -> 162 case get(receive_response_timeout) of 163 Int when is_integer(Int) and (Int > 0) -> 164 Int; 165 _ -> 166 get_timeout(os:type()) 167 end. 168 169get_timeout(_) -> 10000. % Trying to improve test results % 3500. 170 171 172%%---------------------------------------------------------------------- 173%% Receives a trap from the agent. 174%% Returns: TrapPdu|{error, Reason} 175%%---------------------------------------------------------------------- 176receive_trap(Timeout) -> 177 d("await trap within ~w ms",[Timeout]), 178 receive 179 {snmp_pdu, PDU} when is_record(PDU, trappdu) -> 180 d("received trap-PDU: ~n\t~p",[PDU]), 181 PDU 182 after Timeout -> 183 d("trap timeout",[]), 184 {error, timeout} 185 end. 186 187%%---------------------------------------------------------------------- 188%% Options: List of 189%% {agent_udp, UDPPort}, {agent, Agent} 190%% Optional: 191%% {community, String ("public" is default}, quiet, 192%% {mibs, List of Filenames}, {trap_udp, UDPPort (default 5000)}, 193%%---------------------------------------------------------------------- 194init({Options, CallerPid}) -> 195 %% This causes "verbosity printouts" to print (from level debug) 196 %% in the modules we "borrow" from the agent code (burr,,,) 197 %% With "our" name (mgr). 198 put(sname, mgr), 199 put(verbosity, debug), 200 %% Make use of the "test name" print "feature" 201 put(tname, "MGR"), 202 ?SNMP_RAND_SEED(), 203 case (catch is_options_ok(Options)) of 204 true -> 205 put(debug, get_value(debug, Options, false)), 206 d("init -> extract options"), 207 PacksDbg = get_value(packet_server_debug, Options, false), 208 ?IPRINT("init -> PacksDbg: ~p", [PacksDbg]), 209 RecBufSz = get_value(recbuf, Options, 1024), 210 ?IPRINT("init -> RecBufSz: ~p", [RecBufSz]), 211 Mibs = get_value(mibs, Options, []), 212 ?IPRINT("init -> Mibs: " 213 "~n ~tp", [Mibs]), 214 Udp = get_value(agent_udp, Options, 4000), 215 ?IPRINT("init -> Udp: ~p", [Udp]), 216 User = get_value(user, Options, "initial"), 217 ?IPRINT("init -> User: ~p", [User]), 218 EngineId = get_value(engine_id, Options, "agentEngine"), 219 ?IPRINT("init -> EngineId: ~p", [EngineId]), 220 CtxEngineId = get_value(context_engine_id, Options, EngineId), 221 ?IPRINT("init -> CtxEngineId: ~p", [CtxEngineId]), 222 TrapUdp = get_value(trap_udp, Options, 5000), 223 ?IPRINT("init -> TrapUdp: ~p", [TrapUdp]), 224 Dir = get_value(dir, Options, "."), 225 ?IPRINT("init -> Dir: ~p", [Dir]), 226 SecLevel = get_value(sec_level, Options, noAuthNoPriv), 227 ?IPRINT("init -> SecLevel: ~p", [SecLevel]), 228 MiniMIB = snmp_mini_mib:create(Mibs), 229 d("init -> MiniMIB: " 230 "~n ~p", [MiniMIB]), 231 Version = case lists:member(v2, Options) of 232 true -> 'version-2'; 233 false -> 234 case lists:member(v3, Options) of 235 true -> 'version-3'; 236 false -> 'version-1' 237 end 238 end, 239 ?IPRINT("init -> Version: ~p", [Version]), 240 Com = case Version of 241 'version-3' -> 242 get_value(context, Options, ""); 243 _ -> 244 get_value(community, Options, "public") 245 end, 246 ?IPRINT("init -> Com: ~p", [Com]), 247 VsnHdrD = 248 {Com, User, EngineId, CtxEngineId, mk_seclevel(SecLevel)}, 249 ?IPRINT("init -> VsnHdrD: ~p", [VsnHdrD]), 250 IpFamily = get_value(ipfamily, Options, inet), 251 ?IPRINT("init -> IpFamily: ~p", [IpFamily]), 252 AgIp = case snmp_misc:assq(agent, Options) of 253 {value, Addr} when is_tuple(Addr) andalso 254 (size(Addr) =:= 4) andalso 255 (IpFamily =:= inet) -> 256 ?IPRINT("init -> Addr: ~p", [Addr]), 257 Addr; 258 {value, Addr} when is_tuple(Addr) andalso 259 (size(Addr) =:= 8) andalso 260 (IpFamily =:= inet6) -> 261 ?IPRINT("init -> Addr: ~p", [Addr]), 262 Addr; 263 {value, Host} when is_list(Host) -> 264 ?IPRINT("init -> Host: ~p", [Host]), 265 {ok, Ip} = snmp_misc:ip(Host, IpFamily), 266 Ip 267 end, 268 ?IPRINT("init -> AgIp: ~p", [AgIp]), 269 Quiet = lists:member(quiet, Options), 270 ?IPRINT("init -> Quiet: ~p", [Quiet]), 271 PackServ = 272 start_packet_server( 273 Quiet, Options, CallerPid, AgIp, Udp, TrapUdp, 274 VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily), 275 d("init -> packet server: ~p",[PackServ]), 276 State = #state{parent = CallerPid, 277 quiet = Quiet, 278 mini_mib = MiniMIB, 279 packet_server = PackServ}, 280 d("init -> done",[]), 281 {ok, State}; 282 283 {error, Reason} -> 284 {stop,Reason} 285 end. 286 287start_packet_server(false, _Options, _CallerPid, AgIp, Udp, TrapUdp, 288 VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily) -> 289 d("start_packet_server -> entry", []), 290 ?PACK_SERV:start_link_packet( 291 {msg, self()}, AgIp, Udp, TrapUdp, 292 VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily); 293start_packet_server(true, Options, CallerPid, AgIp, Udp, TrapUdp, 294 VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily) -> 295 Type = get_value(receive_type, Options, pdu), 296 d("start_packet_server -> entry with" 297 "~n CallerPid: ~p" 298 "~n when" 299 "~n Type: ~p",[CallerPid, Type]), 300 ?PACK_SERV:start_link_packet( 301 {Type, CallerPid}, AgIp, Udp, TrapUdp, 302 VsnHdrD, Version, Dir, RecBufSz, PacksDbg, IpFamily). 303 304is_options_ok([{mibs,List}|Opts]) when is_list(List) -> 305 is_options_ok(Opts); 306is_options_ok([quiet|Opts]) -> 307 is_options_ok(Opts); 308is_options_ok([{agent,_}|Opts]) -> 309 is_options_ok(Opts); 310is_options_ok([{ipfamily,IpFamily}|Opts]) 311 when IpFamily =:= inet; 312 IpFamily =:= inet6 -> 313 is_options_ok(Opts); 314is_options_ok([{agent_udp,Int}|Opts]) when is_integer(Int) -> 315 is_options_ok(Opts); 316is_options_ok([{agent_udp, {IntR, IntT}}|Opts]) when is_integer(IntR) andalso 317 is_integer(IntT) -> 318 is_options_ok(Opts); 319is_options_ok([{trap_udp,Int}|Opts]) when is_integer(Int) -> 320 is_options_ok(Opts); 321is_options_ok([{community,List}|Opts]) when is_list(List) -> 322 is_options_ok(Opts); 323is_options_ok([{dir,List}|Opts]) when is_list(List) -> 324 is_options_ok(Opts); 325is_options_ok([{sec_level,noAuthNoPriv}|Opts]) -> 326 is_options_ok(Opts); 327is_options_ok([{sec_level,authNoPriv}|Opts]) -> 328 is_options_ok(Opts); 329is_options_ok([{sec_level,authPriv}|Opts]) -> 330 is_options_ok(Opts); 331is_options_ok([{context,List}|Opts]) when is_list(List) -> 332 is_options_ok(Opts); 333is_options_ok([{user,List}|Opts]) when is_list(List) -> 334 is_options_ok(Opts); 335is_options_ok([{engine_id,List}|Opts]) when is_list(List) -> 336 is_options_ok(Opts); 337is_options_ok([{context_engine_id,List}|Opts]) when is_list(List) -> 338 is_options_ok(Opts); 339is_options_ok([v1|Opts]) -> 340 is_options_ok(Opts); 341is_options_ok([v2|Opts]) -> 342 is_options_ok(Opts); 343is_options_ok([v3|Opts]) -> 344 is_options_ok(Opts); 345is_options_ok([{debug,Bool}|Opts]) -> 346 case is_bool(Bool) of 347 ok -> 348 is_options_ok(Opts); 349 error -> 350 {error, {bad_option, debug, Bool}} 351 end; 352is_options_ok([{packet_server_debug,Bool}|Opts]) -> 353 case is_bool(Bool) of 354 ok -> 355 is_options_ok(Opts); 356 error -> 357 {error, {bad_option, packet_server_debug, Bool}} 358 end; 359is_options_ok([{recbuf,Sz}|Opts]) when (0 < Sz) and (Sz =< 65535) -> 360 is_options_ok(Opts); 361is_options_ok([InvOpt|_]) -> 362 {error,{invalid_option,InvOpt}}; 363is_options_ok([]) -> true. 364 365is_bool(true) -> ok; 366is_bool(false) -> ok; 367is_bool(_) -> error. 368 369mk_seclevel(noAuthNoPriv) -> 0; 370mk_seclevel(authNoPriv) -> 1; 371mk_seclevel(authPriv) -> 3. 372 373 374handle_call({purify_oid, Oid}, _From, #state{mini_mib = MiniMib} = State) -> 375 d("handle_call -> purify_oid for ~p",[Oid]), 376 Reply = (catch purify_oid(Oid, MiniMib)), 377 {reply, Reply, State}; 378 379handle_call({find_pure_oid, XOid}, _From, State) -> 380 d("handle_call -> find_pure_oid for ~p",[XOid]), 381 {reply, catch flatten_oid(XOid, State#state.mini_mib), State}; 382 383handle_call({oid_to_name, Oid}, _From, State) -> 384 d("handle_call -> oid_to_name for Oid: ~p",[Oid]), 385 Reply = 386 case lists:keysearch(Oid, 1, State#state.mini_mib) of 387 {value, {_Oid, Name, _Type}} -> 388 {ok, Name}; 389 false -> 390 {error, {no_such_oid, Oid}} 391 end, 392 {reply, Reply, State}; 393 394handle_call({name_to_oid, Name}, _From, State) -> 395 d("handle_call -> name_to_oid for Name: ~p",[Name]), 396 Reply = 397 case lists:keysearch(Name, 2, State#state.mini_mib) of 398 {value, {Oid, _Name, _Type}} -> 399 {ok, Oid}; 400 false -> 401 {error, {no_such_name, Name}} 402 end, 403 {reply, Reply, State}; 404 405handle_call(stop, _From, #state{mini_mib = MiniMIB} = State) -> 406 d("handle_call -> stop request",[]), 407 snmp_mini_mib:delete(MiniMIB), 408 {stop, normal, ok, State#state{mini_mib = undefined}}; 409 410handle_call(discovery, _From, State) -> 411 d("handle_call -> discovery",[]), 412 {Reply, NewState} = execute_discovery(State), 413 {reply, Reply, NewState}. 414 415 416handle_cast({get, Oids}, State) -> 417 d("handle_cast -> get request for ~p", [Oids]), 418 {noreply, execute_request(get, Oids, State)}; 419 420handle_cast({set, VariablesAndValues}, State) -> 421 d("handle_cast -> set request for ~p", [VariablesAndValues]), 422 {noreply, execute_request(set, VariablesAndValues, State)}; 423 424handle_cast({get_next, Oids}, State) -> 425 d("handle_cast -> get-next request for ~p", [Oids]), 426 {noreply, execute_request(get_next, Oids, State)}; 427 428handle_cast(iter_get_next, State) 429 when is_record(State#state.last_received_pdu, pdu) -> 430 d("handle_cast -> iter_get_next request", []), 431 PrevPDU = State#state.last_received_pdu, 432 Oids = [get_oid_from_varbind(Vb) || Vb <- PrevPDU#pdu.varbinds], 433 {noreply, execute_request(get_next, Oids, State)}; 434 435handle_cast(iter_get_next, State) -> 436 ?EPRINT("[Iterated get-next] No Response PDU to " 437 "start iterating from.", []), 438 {noreply, State}; 439 440handle_cast({iter_get_next, N}, State) -> 441 d("handle_cast -> iter_get_next(~p) request",[N]), 442 if 443 is_record(State#state.last_received_pdu, pdu) -> 444 PDU = get_next_iter_impl(N, State#state.last_received_pdu, 445 State#state.mini_mib, 446 State#state.packet_server), 447 {noreply, State#state{last_received_pdu = PDU}}; 448 true -> 449 ?EPRINT("[Iterated get-next] No Response PDU to " 450 "start iterating from.", []), 451 {noreply, State} 452 end; 453 454handle_cast(resend_pdu, #state{last_sent_pdu = PDU} = State) -> 455 d("handle_cast -> resend_pdu request when" 456 "~n PDU = ~p", [PDU]), 457 send_pdu(PDU#pdu{request_id = make_request_id()}, 458 State#state.mini_mib, 459 State#state.packet_server), 460 {noreply, State}; 461 462handle_cast({bulk, Args}, State) -> 463 d("handle_bulk -> bulk request for ~p", [Args]), 464 {noreply, execute_request(bulk, Args, State)}; 465 466handle_cast({response, RespPdu}, State) -> 467 d("handle_cast -> response request with " 468 "~n ~p", [RespPdu]), 469 ?PACK_SERV:send_pdu(RespPdu, State#state.packet_server), 470 {noreply, State}; 471 472handle_cast({send_bytes, Bytes}, State) -> 473 d("handle_cast -> send-bytes request for ~p bytes", [sizeOf(Bytes)]), 474 ?PACK_SERV:send_bytes(Bytes, State#state.packet_server), 475 {noreply, State}; 476 477handle_cast(Msg, State) -> 478 d("handle_cast -> unknown message: " 479 "~n ~p", [Msg]), 480 {noreply, State}. 481 482 483handle_info({snmp_msg, Msg, Ip, Udp}, State) -> 484 io:format("* Got PDU: ~s", [?PACK_SERV:format_hdr(Msg)]), 485 PDU = ?PACK_SERV:get_pdu(Msg), 486 echo_pdu(PDU, State#state.mini_mib), 487 case PDU#pdu.type of 488 'inform-request' -> 489 %% Generate a response... 490 RespPDU = PDU#pdu{type = 'get-response', 491 error_status = noError, 492 error_index = 0}, 493 RespMsg = ?PACK_SERV:set_pdu(Msg, RespPDU), 494 ?PACK_SERV:send_msg(RespMsg, State#state.packet_server, Ip, Udp); 495 _Else -> 496 ok 497 end, 498 {noreply, State#state{last_received_pdu = PDU}}; 499 500handle_info({'EXIT', Pid, Reason}, #state{packet_server = Pid} = State) -> 501 error_logger:error_msg("Received unexpected exit signal from Packet Server ~p: " 502 "~n ~p", [Pid, Reason]), 503 {stop, State#state{packet_server = undefined}}; 504 505handle_info(Info, State) -> 506 d("handle_info -> unknown info: " 507 "~n ~p", [Info]), 508 {noreply, State}. 509 510 511terminate(Reason, #state{packet_server = Pid} = _State) when is_pid(Pid) -> 512 d("terminate -> with Reason: ~n\t~p", [Reason]), 513 ?PACK_SERV:stop(Pid); 514terminate(Reason, _State) -> 515 d("terminate -> with Reason: ~n\t~p",[Reason]), 516 ok. 517 518 519%%---------------------------------------------------------------------- 520%% Returns: A new State 521%%---------------------------------------------------------------------- 522execute_discovery(State) -> 523 Pdu = make_discovery_pdu(), 524 Reply = ?PACK_SERV:send_discovery_pdu(Pdu, State#state.packet_server), 525 {Reply, State#state{last_sent_pdu = Pdu}}. 526 527 528execute_request(Operation, Data, State) -> 529 case (catch make_pdu(Operation, Data, State#state.mini_mib)) of 530 {error, {Format, Data2}} -> 531 report_error(State, Format, Data2), 532 State; 533 {error, _Reason} -> 534 State; 535 PDU when is_record(PDU, pdu) -> 536 send_pdu(PDU, State#state.mini_mib, State#state.packet_server), 537 State#state{last_sent_pdu = PDU} 538 end. 539 540report_error(#state{quiet = true, parent = Pid}, Format, Args) -> 541 Reason = lists:flatten(io_lib:format(Format, Args)), 542 Pid ! {oid_error, Reason}; 543report_error(_, Format, Args) -> 544 ?EPRINT(Format, Args). 545 546 547get_oid_from_varbind(#varbind{oid = Oid}) -> Oid. 548 549send_pdu(PDU, _MiniMIB, PackServ) -> 550 ?PACK_SERV:send_pdu(PDU, PackServ). 551 552%%---------------------------------------------------------------------- 553%% Purpose: Unnesting of oids like [myTable, 3, 4, "hej", 45] to 554%% [1,2,3,3,4,104,101,106,45] 555%%---------------------------------------------------------------------- 556 557purify_oid([A|T], MiniMib) when is_atom(A) -> 558 Oid2 = 559 case snmp_mini_mib:oid(MiniMib, A) of 560 false -> 561 throw({error, {unknown_aliasname, A}}); 562 Oid -> 563 lists:flatten([Oid|T]) 564 end, 565 {ok, verify_pure_oid(Oid2)}; 566purify_oid(L, _) when is_list(L) -> 567 {ok, verify_pure_oid(lists:flatten(L))}; 568purify_oid(X, _) -> 569 {error, {invalid_oid, X}}. 570 571verify_pure_oid([]) -> 572 []; 573verify_pure_oid([H | T]) when is_integer(H) and (H >= 0) -> 574 [H | verify_pure_oid(T)]; 575verify_pure_oid([H | _]) -> 576 throw({error, {not_pure_oid, H}}). 577 578flatten_oid(XOid, DB) -> 579 Oid = case XOid of 580 [A|T] when is_atom(A) -> 581 [remove_atom(A, DB)|T]; 582 L when is_list(L) -> 583 XOid; 584 Shit -> 585 throw({error, 586 {"Invalid oid, not a list of integers: ~w", [Shit]}}) 587 end, 588 check_is_pure_oid(lists:flatten(Oid)). 589 590remove_atom(AliasName, DB) when is_atom(AliasName) -> 591 case snmp_mini_mib:oid(DB, AliasName) of 592 false -> 593 throw({error, {"Unknown aliasname in oid: ~w", [AliasName]}}); 594 Oid -> 595 Oid 596 end; 597remove_atom(X, _DB) -> 598 X. 599 600%%---------------------------------------------------------------------- 601%% Throws if not a list of integers 602%%---------------------------------------------------------------------- 603check_is_pure_oid([]) -> []; 604check_is_pure_oid([X | T]) when is_integer(X) and (X >= 0) -> 605 [X | check_is_pure_oid(T)]; 606check_is_pure_oid([X | _T]) -> 607 throw({error, {"Invalid oid, it contains a non-integer: ~w", [X]}}). 608 609get_next_iter_impl(0, PrevPDU, _MiniMIB, _PackServ) -> 610 PrevPDU; 611get_next_iter_impl(N, PrevPDU, MiniMIB, PackServ) -> 612 Oids = [get_oid_from_varbind(Vb) || Vb <- PrevPDU#pdu.varbinds], 613 PDU = make_pdu(get_next, Oids, MiniMIB), 614 send_pdu(PDU, MiniMIB, PackServ), 615 case receive_response() of 616 {error, timeout} -> 617 io:format("(timeout)~n"), 618 get_next_iter_impl(N, PrevPDU, MiniMIB, PackServ); 619 {error, _Reason} -> 620 PrevPDU; 621 RPDU when is_record(RPDU, pdu) -> 622 io:format("(~w)", [N]), 623 echo_pdu(RPDU, MiniMIB), 624 get_next_iter_impl(N-1, RPDU, MiniMIB, PackServ) 625 end. 626 627%%-------------------------------------------------- 628%% Used to resend a PDU. Takes the old PDU and 629%% generates a fresh one (with a new requestID). 630%%-------------------------------------------------- 631 632make_pdu(set, VarsAndValues, MiniMIB) -> 633 VBs = [var_and_value_to_varbind(VAV, MiniMIB) || VAV <- VarsAndValues], 634 make_pdu_impl(set, VBs); 635make_pdu(bulk, {NonRepeaters, MaxRepetitions, Oids}, MiniMIB) -> 636 Foids = [flatten_oid(Oid, MiniMIB) || Oid <- Oids], 637 #pdu{type = 'get-bulk-request', 638 request_id = make_request_id(), 639 error_status = NonRepeaters, 640 error_index = MaxRepetitions, 641 varbinds = [make_vb(Oid) || Oid <- Foids]}; 642make_pdu(Operation, Oids, MiniMIB) -> 643 Foids = [flatten_oid(Oid, MiniMIB) || Oid <- Oids], 644 make_pdu_impl(Operation, Foids). 645 646make_pdu_impl(get, Oids) -> 647 #pdu{type = 'get-request', 648 request_id = make_request_id(), 649 error_status = noError, 650 error_index = 0, 651 varbinds = [make_vb(Oid) || Oid <- Oids]}; 652 653make_pdu_impl(get_next, Oids) -> 654 #pdu{type = 'get-next-request', 655 request_id = make_request_id(), 656 error_status = noError, 657 error_index = 0, 658 varbinds = [make_vb(Oid) || Oid <- Oids]}; 659 660make_pdu_impl(set, Varbinds) -> 661 #pdu{type = 'set-request', 662 request_id = make_request_id(), 663 error_status = noError, 664 error_index = 0, 665 varbinds = Varbinds}. 666 667make_discovery_pdu() -> 668 make_pdu_impl(get, []). 669 670var_and_value_to_varbind({Oid, Type, Value}, MiniMIB) -> 671 Oid2 = flatten_oid(Oid, MiniMIB), 672 #varbind{oid = Oid2, 673 variabletype = char_to_type(Type), 674 value = Value}; 675var_and_value_to_varbind({XOid, Value}, MiniMIB) -> 676 Oid = flatten_oid(XOid, MiniMIB), 677 #varbind{oid = Oid, 678 variabletype = snmp_mini_mib:type(MiniMIB, Oid), 679 value = Value}. 680 681char_to_type(o) -> 682 'OBJECT IDENTIFIER'; 683char_to_type(i) -> 684 'INTEGER'; 685char_to_type(u) -> 686 'Unsigned32'; 687char_to_type(g) -> % Gauge, Gauge32 688 'Unsigned32'; 689char_to_type(s) -> 690 'OCTET STRING'. 691 692make_vb(Oid) -> 693 #varbind{oid = Oid, variabletype = 'NULL', value = 'NULL'}. 694 695make_request_id() -> 696 snmp_test_mgr_counter_server:increment(mgr_request_id, 1, 1, 2147483647). 697 698echo_pdu(PDU, MiniMIB) -> 699 io:format("~s", [snmp_misc:format_pdu(PDU, MiniMIB)]). 700 701 702%%---------------------------------------------------------------------- 703%% Test Sequence 704%%---------------------------------------------------------------------- 705echo_errors({error, Id, {ExpectedFormat, ExpectedData}, {Format, Data}})-> 706 ?EPRINT("*** Unexpected Behaviour *** Id: ~w" 707 "~n Expected: " ++ ExpectedFormat ++ 708 "~n Got: " ++ Format ++ "~n", 709 [Id] ++ ExpectedData ++ Data), 710 {error, Id, {ExpectedFormat, ExpectedData}, {Format, Data}}; 711echo_errors(ok) -> ok; 712echo_errors({ok, _} = OK) -> OK. 713 714get_response_impl(Id, ExpVars) -> 715 ?IPRINT("await response ~w with" 716 "~n Expected Varbinds: ~p", 717 [Id, ExpVars]), 718 PureVars = find_pure_oids2(ExpVars), 719 case receive_response() of 720 #pdu{type = 'get-response', 721 error_status = noError, 722 error_index = 0, 723 varbinds = VBs} -> 724 ?IPRINT("received expected response pdu (~w) - match vars" 725 "~n Expected VBs: ~p" 726 "~n Received VBs: ~p", 727 [Id, PureVars, VBs]), 728 match_vars(Id, PureVars, VBs, []); 729 730 #pdu{type = Type2, 731 request_id = ReqId, 732 error_status = Err2, 733 error_index = Index2} -> 734 ?EPRINT("received unexpected response pdu: ~w, ~w, ~w" 735 "~n Received Error: ~p" 736 "~n Received Index: ~p", 737 [Type2, Id, ReqId, Err2, Index2]), 738 {error, 739 Id, 740 {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", 741 ['get-response', noError, 0, ReqId]}, 742 {"Type: ~w, ErrStat: ~w, Idx: ~w", 743 [Type2, Err2, Index2]}}; 744 745 {error, Reason} -> 746 %% We did not get the message we wanted, 747 %% but what did we get? 748 ?EPRINT("unexpected receive pdu error: ~w" 749 "~n Reason: ~p" 750 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 751 format_reason(Id, Reason) 752 end. 753 754 755 756%%---------------------------------------------------------------------- 757%% Returns: ok | {error, Id, {ExpectedFormat, ExpectedData}, {Format, Data}} 758%%---------------------------------------------------------------------- 759expect_impl(Id, any) -> 760 ?IPRINT("await ~w pdu (any)", [Id]), 761 case receive_response() of 762 PDU when is_record(PDU, pdu) -> 763 ?IPRINT("received expected pdu (~w)", [Id]), 764 ok; 765 {error, Reason} -> 766 %% We did not get the message we wanted, 767 %% but what did we get? 768 ?EPRINT("unexpected receive error: ~w" 769 "~n Reason: ~p" 770 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 771 format_reason(Id, Reason) 772 end; 773 774expect_impl(Id, return) -> 775 ?IPRINT("await ~w pdu", [Id]), 776 case receive_response() of 777 PDU when is_record(PDU, pdu) -> 778 ?IPRINT("received expected pdu (~w)", [Id]), 779 {ok, PDU}; 780 {error, Reason} -> 781 %% We did not get the message we wanted, 782 %% but what did we get? 783 ?EPRINT("unexpected receive error: ~w" 784 "~n Reason: ~p" 785 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 786 format_reason(Id, Reason) 787 end; 788 789expect_impl(Id, trap) -> 790 ?IPRINT("await ~w trap", [Id]), 791 case receive_trap(3500) of 792 PDU when is_record(PDU, trappdu) -> 793 ?IPRINT("received expected trap (~w)", [Id]), 794 ok; 795 {error, Reason} -> 796 %% We did not get the message we wanted, 797 %% but what did we get? 798 ?EPRINT("unexpected receive error: ~w" 799 "~n Reason: ~p" 800 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 801 format_reason(Id, Reason) 802 end; 803 804expect_impl(Id, timeout) -> 805 ?IPRINT("await ~w nothing", [Id]), 806 receive 807 X -> 808 ?EPRINT("received unexpected message: ~w" 809 "~n ~p", 810 [Id, X]), 811 {error, Id, {"Timeout", []}, {"Message ~w", [X]}} 812 after 3500 -> 813 ok 814 end; 815 816expect_impl(Id, Err) when is_atom(Err) -> 817 ?IPRINT("await ~w with" 818 "~n Err: ~p", 819 [Id, Err]), 820 case receive_response() of 821 #pdu{error_status = Err} -> 822 ?IPRINT("received pdu with expected error status (~w, ~w)", 823 [Id, Err]), 824 ok; 825 826 #pdu{type = Type2, 827 request_id = ReqId, 828 error_status = Err2} -> 829 ?EPRINT("received pdu with unexpected error status: ~w, ~w, ~w" 830 "~n Expected Error: ~p" 831 "~n Received Error: ~p", 832 [Type2, Id, ReqId, Err, Err2]), 833 {error, Id, {"ErrorStatus: ~w, RequestId: ~w", [Err,ReqId]}, 834 {"ErrorStatus: ~w", [Err2]}}; 835 836 {error, Reason} -> 837 %% We did not get the message we wanted, 838 %% but what did we get? 839 ?EPRINT("unexpected receive error: ~w" 840 "~n Reason: ~p" 841 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 842 format_reason(Id, Reason) 843 end; 844 845expect_impl(Id, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> 846 ?IPRINT("await ~w with" 847 "~n ExpectedVarbinds: ~p", 848 [Id, ExpectedVarbinds]), 849 PureVars = find_pure_oids(ExpectedVarbinds), 850 case receive_response() of 851 #pdu{type = 'get-response', 852 error_status = noError, 853 error_index = 0, 854 varbinds = VBs} -> 855 ?IPRINT("received expected response pdu (~w) - check varbinds" 856 "~n Expected VBs: ~p" 857 "~n Received VBs: ~p", 858 [Id, PureVars, VBs]), 859 check_vars(Id, PureVars, VBs); 860 861 #pdu{type = Type2, 862 request_id = ReqId, 863 error_status = Err2, 864 error_index = Index2} -> 865 ?EPRINT("received unexpected pdu: ~w, ~w, ~w" 866 "~n Received Error: ~p" 867 "~n Received Index: ~p", 868 [Type2, Id, ReqId, Err2, Index2]), 869 {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", 870 ['get-response', noError, 0, ReqId]}, 871 {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; 872 873 {error, Reason} -> 874 %% We did not get the message we wanted, 875 %% but what did we get? 876 ?EPRINT("unexpected receive error: ~w" 877 "~n Reason: ~p" 878 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 879 format_reason(Id, Reason) 880 end. 881 882expect_impl(Id, v2trap, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> 883 ?IPRINT("await v2 trap ~w with" 884 "~n ExpectedVarbinds: ~p", 885 [Id, ExpectedVarbinds]), 886 PureVars = find_pure_oids(ExpectedVarbinds), 887 case receive_response() of 888 #pdu{type = 'snmpv2-trap', 889 error_status = noError, 890 error_index = 0, 891 varbinds = VBs} -> 892 ?IPRINT("received expected v2 trap (~w) - check varbinds" 893 "~n Expected VBs: ~p" 894 "~n Received VBs: ~p", 895 [Id, PureVars, VBs]), 896 check_vars(Id, PureVars, VBs); 897 898 #pdu{type = Type2, 899 request_id = ReqId, 900 error_status = Err2, 901 error_index = Index2} -> 902 ?EPRINT("received unexpected pdu: ~w, ~w, ~w" 903 "~n Received Error: ~p" 904 "~n Received Index: ~p", 905 [Type2, Id, ReqId, Err2, Index2]), 906 {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", 907 ['snmpv2-trap', noError, 0, ReqId]}, 908 {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; 909 910 {error, Reason} -> 911 %% We did not get the message we wanted, 912 %% but what did we get? 913 ?EPRINT("unexpected receive error: ~w" 914 "~n Reason: ~p" 915 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 916 format_reason(Id, Reason) 917 end; 918 919expect_impl(Id, report, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> 920 ?IPRINT("await report ~w with" 921 "~n ExpectedVarbinds: ~p", 922 [Id, ExpectedVarbinds]), 923 PureVBs = find_pure_oids(ExpectedVarbinds), 924 case receive_response() of 925 #pdu{type = 'report', 926 error_status = noError, 927 error_index = 0, 928 varbinds = VBs} -> 929 ?IPRINT("received expected report (~w) - check varbinds" 930 "~n Expected VBs: ~p" 931 "~n Received VBs: ~p", 932 [Id, PureVBs, VBs]), 933 check_vars(Id, PureVBs, VBs); 934 935 #pdu{type = Type2, 936 request_id = ReqId, 937 error_status = Err2, 938 error_index = Index2} -> 939 ?EPRINT("received unexpected pdu: ~w, ~w, ~w" 940 "~n Received Error: ~p" 941 "~n Received Index: ~p", 942 [Type2, Id, ReqId, Err2, Index2]), 943 {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", 944 [report, noError, 0, ReqId]}, 945 {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; 946 947 {error, Reason} -> 948 %% We did not get the message we wanted, 949 %% but what did we get? 950 ?EPRINT("unexpected receive error: ~w" 951 "~n Reason: ~p" 952 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 953 format_reason(Id, Reason) 954 end; 955 956expect_impl(Id, {inform, Reply}, ExpectedVarbinds) 957 when is_list(ExpectedVarbinds) -> 958 ?IPRINT("await inform ~w with" 959 "~n Reply: ~p" 960 "~n ExpectedVarbinds: ~p", 961 [Id, Reply, ExpectedVarbinds]), 962 PureVBs = find_pure_oids(ExpectedVarbinds), 963 Resp = receive_response(), 964 case Resp of 965 #pdu{type = 'inform-request', 966 error_status = noError, 967 error_index = 0, 968 varbinds = VBs} -> 969 ?IPRINT("received inform (~w) - check varbinds" 970 "~n Expected VBs: ~p" 971 "~n Received VBs: ~p", 972 [Id, PureVBs, VBs]), 973 case check_vars(Id, PureVBs, VBs) of 974 ok when (Reply == true) -> 975 ?IPRINT("varbinds ok (~w) - send ok inform response", [Id]), 976 RespPDU = Resp#pdu{type = 'get-response', 977 error_status = noError, 978 error_index = 0}, 979 ?MODULE:rpl(RespPDU), 980 ok; 981 ok when (element(1, Reply) == error) -> 982 ?IPRINT("varbinds ok (~w) - send error inform response", [Id]), 983 {error, Status, Index} = Reply, 984 RespPDU = Resp#pdu{type = 'get-response', 985 error_status = Status, 986 error_index = Index}, 987 ?MODULE:rpl(RespPDU), 988 ok; 989 ok when (Reply == false) -> 990 ?IPRINT("varbinds ok (~w) - don't send inform response", [Id]), 991 ok; 992 Else -> 993 ?EPRINT("unexpected (inform) varbinds (~w):" 994 "~n VBs: ~p" 995 "~n ~p", [Id, VBs, Else]), 996 Else 997 end; 998 999 #pdu{type = Type2, 1000 request_id = ReqId, 1001 error_status = Err2, 1002 error_index = Index2} -> 1003 ?EPRINT("received unexpected pdu: ~w, ~w, ~w" 1004 "~n Received Error: ~p" 1005 "~n Received Index: ~p", 1006 [Type2, Id, ReqId, Err2, Index2]), 1007 {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", 1008 ['inform-request', noError, 0, ReqId]}, 1009 {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; 1010 1011 {error, Reason} -> 1012 %% We did not get the message we wanted, 1013 %% but what did we get? 1014 ?EPRINT("unexpected receive error: ~w" 1015 "~n Reason: ~p" 1016 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 1017 format_reason(Id, Reason) 1018 end. 1019 1020expect_impl(Id, Err, Index, any = _ExpectedVarbinds) -> 1021 ?IPRINT("await response ~w with" 1022 "~n Err: ~p" 1023 "~n Index: ~p" 1024 "~n ExpectedVarbinds: ~p", 1025 [Id, Err, Index, _ExpectedVarbinds]), 1026 case receive_response() of 1027 #pdu{type = 'get-response', 1028 error_status = Err, 1029 error_index = Index} -> 1030 ?IPRINT("received expected response pdu (~w, ~w, ~w)", 1031 [Id, Err, Index]), 1032 ok; 1033 1034 #pdu{type = 'get-response', 1035 error_status = Err} when (Index == any) -> 1036 ?IPRINT("received expected response pdu (~w, ~w)", 1037 [Id, Err]), 1038 ok; 1039 1040 #pdu{type = 'get-response', 1041 request_id = ReqId, 1042 error_status = Err, 1043 error_index = Idx} when is_list(Index) -> 1044 case lists:member(Idx, Index) of 1045 true -> 1046 ?IPRINT("received expected response pdu (~w, ~w, ~w)", 1047 [Id, Err, Idx]), 1048 ok; 1049 false -> 1050 ?EPRINT("received response pdu with unexpected index (~w, ~w):" 1051 "~n Expected Index: ~p" 1052 "~n Received Index: ~p", 1053 [Id, Err, Index, Idx]), 1054 {error, Id, {"ErrStat: ~w, Idx: ~w, RequestId: ~w", 1055 [Err, Index, ReqId]}, 1056 {"ErrStat: ~w, Idx: ~w", [Err, Idx]}} 1057 end; 1058 1059 #pdu{type = Type2, 1060 request_id = ReqId, 1061 error_status = Err2, 1062 error_index = Index2} -> 1063 ?EPRINT("received unexpected response pdu: ~w, ~w, ~w" 1064 "~n Expected Error: ~p" 1065 "~n Received Error: ~p" 1066 "~n Expected Index: ~p" 1067 "~n Received Index: ~p", 1068 [Type2, Id, ReqId, Err, Err2, Index, Index2]), 1069 {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", 1070 ['get-response', Err, Index, ReqId]}, 1071 {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; 1072 1073 {error, Reason} -> 1074 %% We did not get the message we wanted, 1075 %% but what did we get? 1076 ?EPRINT("unexpected (receive) response: " 1077 "~n Reason: ~p" 1078 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 1079 format_reason(Id, Reason) 1080 end; 1081 1082expect_impl(Id, Err, Index, ExpectedVarbinds) -> 1083 ?IPRINT("await response ~w with" 1084 "~n Err: ~p" 1085 "~n Index: ~p" 1086 "~n ExpectedVarbinds: ~p", 1087 [Id, Err, Index, ExpectedVarbinds]), 1088 PureVBs = find_pure_oids(ExpectedVarbinds), 1089 case receive_response() of 1090 #pdu{type = 'get-response', 1091 error_status = Err, 1092 error_index = Index, 1093 varbinds = VBs} -> 1094 ?IPRINT("received expected response pdu (~w, ~w, ~w) - check varbinds" 1095 "~n Expected VBs: ~p" 1096 "~n Received VBs: ~p", 1097 [Id, Err, Index, PureVBs, VBs]), 1098 check_vars(Id, PureVBs, VBs); 1099 1100 #pdu{type = 'get-response', 1101 error_status = Err, 1102 varbinds = VBs} when (Index == any) -> 1103 ?IPRINT("received expected response pdu (~w, ~w) - check varbinds" 1104 "~n Expected VBs: ~p" 1105 "~n Received VBs: ~p", 1106 [Id, Err, PureVBs, VBs]), 1107 check_vars(Id, PureVBs, VBs); 1108 1109 #pdu{type = 'get-response', 1110 request_id = ReqId, 1111 error_status = Err, 1112 error_index = Idx, 1113 varbinds = VBs} when is_list(Index) -> 1114 case lists:member(Idx, Index) of 1115 true -> 1116 ?IPRINT("received expected pdu (~w, ~w, ~w) - check varbinds" 1117 "~n Expected VBs: ~p" 1118 "~n Received VBs: ~p", 1119 [Id, Err, Idx, PureVBs, VBs]), 1120 check_vars(Id, PureVBs, VBs); 1121 false -> 1122 ?EPRINT("received response pdu with unexpected index (~w, ~w):" 1123 "~n Expected Index: ~p" 1124 "~n Received Index: ~p" 1125 "~n Expected VBs: ~p" 1126 "~n Received VBs: ~p", 1127 [Id, Err, Index, Idx, PureVBs, VBs]), 1128 {error,Id, 1129 {"ErrStat: ~w, Idx: ~w, Varbinds: ~w, RequestId: ~w", 1130 [Err,Index,PureVBs,ReqId]}, 1131 {"ErrStat: ~w, Idx: ~w, Varbinds: ~w", 1132 [Err,Idx,VBs]}} 1133 end; 1134 1135 #pdu{type = Type2, 1136 request_id = ReqId, 1137 error_status = Err2, 1138 error_index = Index2, 1139 varbinds = VBs} -> 1140 ?EPRINT("received unexpected response pdu: ~w, ~w, ~w" 1141 "~n Expected Error: ~p" 1142 "~n Received Error: ~p" 1143 "~n Expected Index: ~p" 1144 "~n Received Index: ~p" 1145 "~n Expected VBs: ~p" 1146 "~n Received VBs: ~p", 1147 [Type2, Id, ReqId, 1148 Err, Err2, Index, Index2, PureVBs, VBs]), 1149 {error,Id, 1150 {"Type: ~w, ErrStat: ~w, Idx: ~w, Varbinds: ~w, RequestId: ~w", 1151 ['get-response',Err,Index,PureVBs,ReqId]}, 1152 {"Type: ~w, ErrStat: ~w Idx: ~w Varbinds: ~w", 1153 [Type2,Err2,Index2,VBs]}}; 1154 1155 {error, Reason} -> 1156 %% We did not get the message we wanted, 1157 %% but what did we get? 1158 ?EPRINT("unexpected receive pdu error: ~w" 1159 "~n Reason: ~p" 1160 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 1161 format_reason(Id, Reason) 1162 end. 1163 1164expect_impl(Id, trap, Enterp, Generic, Specific, ExpectedVarbinds) -> 1165 ?IPRINT("await trap pdu ~w with" 1166 "~n Enterprise: ~p" 1167 "~n Generic: ~p" 1168 "~n Specific: ~p" 1169 "~n ExpectedVarbinds: ~p", 1170 [Id, Enterp, Generic, Specific, ExpectedVarbinds]), 1171 PureE = find_pure_oid(Enterp), 1172 PureVBs = find_pure_oids(ExpectedVarbinds), 1173 case receive_trap(3500) of 1174 #trappdu{enterprise = PureE, 1175 generic_trap = Generic, 1176 specific_trap = Specific, 1177 varbinds = VBs} -> 1178 ?IPRINT("received expected trap pdu - check varbinds" 1179 "~n Expected VBs: ~p" 1180 "~n Received VBs: ~p", 1181 [PureVBs, VBs]), 1182 check_vars(Id, PureVBs, VBs); 1183 1184 #trappdu{enterprise = Ent2, 1185 generic_trap = G2, 1186 specific_trap = Spec2, 1187 varbinds = VBs} -> 1188 ?EPRINT("received unexpected trap pdu: ~w" 1189 "~n Expected Enterprise: ~p" 1190 "~n Received Enterprise: ~p" 1191 "~n Expected Generic: ~p" 1192 "~n Received Generic: ~p" 1193 "~n Expected Specific: ~p" 1194 "~n Received Specific: ~p" 1195 "~n Expected VBs: ~p" 1196 "~n Received VBs: ~p", 1197 [Id, 1198 PureE, Ent2, 1199 Generic, G2, 1200 Specific, Spec2, 1201 PureVBs, VBs]), 1202 {error, Id, 1203 {"Enterprise: ~w, Generic: ~w, Specific: ~w, Varbinds: ~w", 1204 [PureE, Generic, Specific, ExpectedVarbinds]}, 1205 {"Enterprise: ~w, Generic: ~w, Specific: ~w, Varbinds: ~w", 1206 [Ent2, G2, Spec2, VBs]}}; 1207 1208 {error, Reason} -> 1209 %% We did not get the message we wanted, 1210 %% but what did we get? 1211 ?EPRINT("unexpected receive trap pdu error: ~w" 1212 "~n Reason: ~p" 1213 "~n Msg Que: ~p", [Id, Reason, ?MQUEUE()]), 1214 format_reason(Id, Reason) 1215 end. 1216 1217format_reason(Id, Reason) -> 1218 {error, Id, {"?", []}, {"~w", [Reason]}}. 1219 1220 1221%%---------------------------------------------------------------------- 1222%% Args: Id, ExpectedVarbinds, GotVarbinds 1223%% Returns: ok 1224%% Fails: if not ok 1225%%---------------------------------------------------------------------- 1226check_vars(_Id,[], []) -> 1227 ok; 1228check_vars(Id,Vars, []) -> 1229 {error, Id, {"More Varbinds (~w)", [Vars]}, {"Too few", []}}; 1230check_vars(Id,[], Varbinds) -> 1231 {error,Id, {"Fewer Varbinds", []}, {"Too many (~w)", [Varbinds]}}; 1232check_vars(Id,[{_XOid, any} | Vars], [#varbind{oid = _Oid} |Vbs]) -> 1233 check_vars(Id,Vars, Vbs); 1234check_vars(Id,[{Oid, Val} | Vars], [#varbind{oid = Oid, value = Val} |Vbs]) -> 1235 check_vars(Id,Vars, Vbs); 1236check_vars(Id,[{Oid, Val} | _], [#varbind{oid = Oid, value = Val2} |_]) -> 1237 {error, Id, {" Varbind: ~w = ~w", [Oid, Val]}, {"Value: ~w", [Val2]}}; 1238check_vars(Id,[{Oid, _Val} | _], [#varbind{oid = Oid2, value = _Val2} |_]) -> 1239 {error, Id, {"Oid: ~w", [Oid]}, {"Oid: ~w", [Oid2]}}. 1240 1241match_vars(Id, [Oid|T], [#varbind{oid = Oid, value = Value} | Vbs], Res) -> 1242 match_vars(Id, T, Vbs, [Value | Res]); 1243match_vars(_Id, [], [], Res) -> 1244 {ok, lists:reverse(Res)}; 1245match_vars(Id, [Oid | _], [#varbind{oid = Oid2}], _Res) -> 1246 {error, Id, {" Oid: ~w", [Oid]}, {"Oid2: ~w", [Oid2]}}; 1247match_vars(Id, Vars, [], _Res) -> 1248 {error, Id, {"More Varbinds (~w)", [Vars]}, {"Too few", []}}; 1249match_vars(Id, [], Varbinds, _Res) -> 1250 {error,Id, {"Fewer Varbinds", []}, {"Too many (~w)", [Varbinds]}}. 1251 1252 1253 1254find_pure_oids([]) -> []; 1255find_pure_oids([{XOid, Q}|T]) -> 1256 [{find_pure_oid(XOid), Q} | find_pure_oids(T)]. 1257 1258find_pure_oids2([]) -> []; 1259find_pure_oids2([XOid|T]) -> 1260 [find_pure_oid(XOid) | find_pure_oids2(T)]. 1261 1262 1263%%---------------------------------------------------------------------- 1264%% Returns: Oid 1265%% Fails: malformed oids 1266%%---------------------------------------------------------------------- 1267find_pure_oid(XOid) -> 1268 case gen_server:call(?MODULE, {find_pure_oid, XOid}, infinity) of 1269 {error, {Format, Data}} -> 1270 ok = io:format(Format, Data), 1271 exit(malformed_oid); 1272 Oid when is_list(Oid) -> Oid 1273 end. 1274 1275get_value(Opt, Opts, Default) -> 1276 case snmp_misc:assq(Opt,Opts) of 1277 {value, C} -> C; 1278 false -> Default 1279 end. 1280 1281 1282%%---------------------------------------------------------------------- 1283 1284call(Req) -> 1285 call(Req, infinity). 1286 1287call(Req, To) -> 1288 gen_server:call(?SERVER, Req, To). 1289 1290cast(Msg) -> 1291 gen_server:cast(?SERVER, Msg). 1292 1293 1294%%---------------------------------------------------------------------- 1295%% Debug 1296%%---------------------------------------------------------------------- 1297 1298sizeOf(L) when is_list(L) -> 1299 length(lists:flatten(L)); 1300sizeOf(B) when is_binary(B) -> 1301 size(B). 1302 1303d(F) -> d(F, []). 1304d(F, A) -> d(get(debug), F, A). 1305 1306d(true, F, A) -> 1307 ?IPRINT(F, A); 1308d(_,_F,_A) -> 1309 ok. 1310 1311