diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/snmp/test | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/snmp/test')
85 files changed, 87700 insertions, 0 deletions
diff --git a/lib/snmp/test/Makefile b/lib/snmp/test/Makefile new file mode 100644 index 0000000000..86af2460f5 --- /dev/null +++ b/lib/snmp/test/Makefile @@ -0,0 +1,259 @@ +#-*-makefile-*- ; force emacs to enter makefile-mode + +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../vsn.mk + +VSN = $(SNMP_VSN) + + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +include modules.mk + +SNMP_ROOT = .. +SNMP_SUITE = snmp_SUITE + +ERL_FILES = $(MODULES:%=%.erl) + +SNMP_TEST_DATA = snmp_test_data + +SNMP_MIB_DIR = $(SNMP_TEST_DATA) + +SNMP_BIN_TARGET_DIR = $(SNMP_TEST_DATA) + +MIB_SOURCE = $(MIB_FILES:%.mib=$(SNMP_MIB_DIR)/%.mib) + +MIB_TARGETS = \ + $(MIB_FILES:%.mib=$(SNMP_BIN_TARGET_DIR)/%.bin) \ + $(MIB_FILES:%.mib=$(SNMP_BIN_TARGET_DIR)/%.hrl) +ERL_TARGETS = $(MODULES:%=$(EBIN)/%.$(EMULATOR)) + +TEST_SERVER_TARGETS = $(TEST_SERVER_MODULES:%=$(EBIN)/%.$(EMULATOR)) + +TARGET_FILES = $(ERL_TARGETS) + +SOURCE = $(ERL_FILES) $(HRL_FILES) + +# The script 'make_emakefile' only exist in R9 and later +# So, if it does not exist, then use the old method +# (compile the erl-files and install the beam-files) +EMAKEFILE = Emakefile +MAKE_EMAKE = $(wildcard $(ERL_TOP)/make/make_emakefile) + +ifeq ($(MAKE_EMAKE),) +BUILDTARGET = $(TARGET_FILES) +RELTEST_FILES = $(SPECS) $(SOURCE) $(TARGET_FILES) +else +BUILDTARGET = $(MIB_TARGETS) emakebuild +RELTEST_FILES = $(EMAKEFILE) $(SPECS) $(SOURCE) +endif + +COVER_SPEC_FILE = snmp.cover + + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/snmp_test + + +# ---------------------------------------------------- +# SNMP FLAGS +# ---------------------------------------------------- +ifeq ($(SNMP_DEBUG),) + SNMP_DEBUG = d +endif + +ifeq ($(SNMP_DEBUG),e) + SNMP_FLAGS += -Dsnmp_error +endif +ifeq ($(SNMP_DEBUG),l) + SNMP_FLAGS += -Dsnmp_log +endif +ifeq ($(SNMP_DEBUG),d) + SNMP_FLAGS += -Dsnmp_debug +endif + +ifeq ($(DONT_USE_TS),true) + SNMP_FLAGS += -DDONT_USE_TEST_SERVER +endif + +SNMP_MIB_FLAGS += -pa ../ebin +version + +ifneq ($(MIBS_VERBOSITY),) + SNMP_MIB_FLAGS += +'{verbosity,$(MIBS_VERBOSITY)}' +endif + +ifeq ($(SNMP_DESC),true) + USE_DESCRIPTION = +'{description,true}' +endif + +GROUP_CHECK = +'{group_check,false}' + +SNMP_MIB_FLAGS += $(GROUP_CHECK) $(USE_DESCRIPTION) -I$(SNMP_BIN_TARGET_DIR) + +ifndef SUITE +SUITE = snmp_SUITE +endif + +ESTOP = -s init stop + +ifeq ($(DONT_STOP),true) +MAYBE_ESTOP = +else +MAYBE_ESTOP = $(ESTOP) +endif + +ifeq ($(MERL),) +MERL = erl +endif + +ARGS += -noshell + +ifeq ($(DISABLE_TC_TIMEOUT),true) +ARGS += -snmp_test_timeout +endif + + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +EBIN = . + +ERL_COMPILE_FLAGS += -I../src \ + -I$(ERL_TOP)/lib/test_server/include \ + -I../include \ + -Dsnmp_test_data=snmp_test_data \ + -Dversion=\"$(VSN)$(PRE_VSN)\" \ + +'{parse_transform,sys_pre_attributes}' \ + +'{attribute,insert,app_vsn,$(APP_VSN)}' \ + $(SNMP_FLAGS) + +ERL_SNMP_FLAGS = $(SNMP_MIB_FLAGS) \ + -I../priv/mibs + +$(SNMP_BIN_TARGET_DIR)/%.bin: $(SNMP_MIB_DIR)/%.mib + $(ERLC) $(ERL_SNMP_FLAGS) -o $(SNMP_MIB_DIR) $< + +$(SNMP_BIN_TARGET_DIR)/%.hrl: $(SNMP_BIN_TARGET_DIR)/%.bin + $(ERLC) $(ERL_SNMP_FLAGS) -o $(SNMP_BIN_TARGET_DIR) $< + + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +tests debug opt: $(BUILDTARGET) + +.PHONY: emakebuild + +emakebuild: $(EMAKEFILE) + +targets: mib $(EMAKEFILE) + erl -make + +old_targets: $(TARGET_FILES) $(TEST_SERVER_TARGETS) + +$(EMAKEFILE): Makefile + $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) '*_SUITE_make' > $(EMAKEFILE) + $(MAKE_EMAKE) $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES) >> $(EMAKEFILE) + +clean: + rm -f $(EMAKEFILE) + rm -f $(TARGET_FILES) + rm -f core + +docs: + +appup: snmp_appup_mgr.$(EMULATOR) + +mib: $(MIB_TARGETS) + +make: old_targets + +test: make + $(MERL) $(ARGS) -sname snmp_test $(ERL_PATH) \ + -s snmp_test_server run $(SUITE) \ + $(MAYBE_ESTOP) + +agent: make + $(MERL) $(ARGS) -sname snmp_agent_test $(ERL_PATH) \ + -s snmp_test_server run snmp_agent_test \ + $(MAYBE_ESTOP) + +manager: make + $(MERL) $(ARGS) -sname snmp_manager_test $(ERL_PATH) \ + -s snmp_test_server run snmp_manager_test \ + $(MAYBE_ESTOP) + +appup: make + $(MERL) $(ARGS) -sname snmp_appup_test $(ERL_PATH) \ + -s snmp_test_server run snmp_appup_test \ + $(MAYBE_ESTOP) + + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: + +release_tests_spec: opt + $(INSTALL_DIR) $(RELSYSDIR) + $(INSTALL_DATA) $(RELTEST_FILES) $(COVER_SPEC_FILE) $(RELSYSDIR) + chmod -f -R u+w $(RELSYSDIR) + tar cf - snmp_test_data | (cd $(RELSYSDIR); tar xf -) + +release_docs_spec: + + +info: + @echo "SNMP_DEBUG = $(SNMP_DEBUG)" + @echo "SNMP_FLAGS = $(SNMP_FLAGS)" + @echo "" + @echo "SNMP_MIB_DIR = $(SNMP_MIB_DIR)" + @echo "MIB_SOURCE = $(MIB_SOURCE)" + @echo "MIB_TARGETS = $(MIB_TARGETS)" + @echo "SNMP_MIB_FLAGS = $(SNMP_MIB_FLAGS)" + @echo "" + @echo "ERL_COMPILE_FLAGS = $(ERL_COMPILE_FLAGS)" + @echo "" + @echo "RELSYSDIR = $(RELSYSDIR)" + @echo "" + @echo "SOURCE = $(SOURCE)" + @echo "" + @echo "TARGET_FILES = $(TARGET_FILES)" + @echo "" + @echo "EMAKEFILE = $(EMAKEFILE)" + @echo "MAKE_EMAKE = $(MAKE_EMAKE)" + @echo "BUILDTARGET = $(BUILDTARGET)" + @echo "RELTEST_FILES = $(RELTEST_FILES)" + @echo "" + + diff --git a/lib/snmp/test/klas3.erl b/lib/snmp/test/klas3.erl new file mode 100644 index 0000000000..a5ce2af8c5 --- /dev/null +++ b/lib/snmp/test/klas3.erl @@ -0,0 +1,162 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(klas3). +-compile(export_all). + +ftab(new) -> + mnesia:create_table([{name, friendsTable3}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2]}]); + +ftab(delete) -> + ok. + + +ftab(is_set_ok, [2], _Cols) -> +% io:format("calling ftab is_set_ok - fail~n"), + {inconsistentValue, 2}; +ftab(is_set_ok, _, _Cols) -> +% io:format("calling ftab is_set_ok - ok~n"), + {noError, 0}; + +ftab(undo, [3], _Cols) -> +% io:format("calling ftab undo - fail~n"), + {undoFailed, 2}; + +ftab(undo, [1], _Cols) -> +% io:format("calling ftab undo~n"), + {noError, 0}; + +ftab(set, [4], _Cols) -> + {commitFailed, 2}; + +ftab(Op, RowIndex, Cols) -> + snmp_generic:table_func(Op, RowIndex, Cols, {friendsTable3, mnesia}). + + +fname(new) -> ok; +fname(delete) -> ok; +fname(get) -> + Str2 = (catch begin + case snmpa:current_request_id() of + {value, Int} when is_integer(Int) -> ok; + {value, _} -> throw("bad_int"); + _ -> throw("bad_req") + end, + case snmpa:current_community() of + {value, Str} when is_list(Str) -> Str; + {value, _} -> throw("bad_str"); + _ -> throw("bad_com") + end, + case snmpa:current_address() of + {value, {[_A,_B,_C,_D], E}} when is_integer(E) -> ok; + {value, _} -> throw("bad_ip"); + _ -> throw("bad_adr") + end, + case snmpa:current_net_if_data() of + {value, []} -> ok; + {value, _} -> throw("bad_nil"); + _ -> throw("bad_nid") + end, + "ok" + end), + {value, Str2}. + +fname(is_set_ok, "hoj") -> + inconsistentValue; +fname(is_set_ok, "xfail") -> + i_know_this_is_wrong_it_should_be_user_error; +fname(is_set_ok, _) -> +% io:format("calling fname is_set_ok~n"), + noError; +fname(set, "fel") -> commitFailed; +fname(set, _) -> noError; +fname(undo, "ufail") -> +% io:format("calling fname undo - fail~n"), + undoFailed; +fname(undo, _) -> +% io:format("calling fname undo~n"), + noError. + +%% snmp_mgr:s([{[fStatus2, 1], 4}, {[fname2,0], "ok"}]). -> noError +%% snmp_mgr:s([{[fStatus2, 1], 4}, {[fname2,0], "hoj"}]). -> {badValue, 2} +%% snmp_mgr:s([{[fStatus2, 3], 4}, {[fname2,0], "hoj"}]). -> {genErr, 1} +%% snmp_mgr:s([{[fStatus2, 4], 4}, {[fname2,0], "ok"}]). -> {genErr, 1} +%% snmp_mgr:s([{[fStatus2, 4], 4}, {[fname2,0], "ufail"}]). -> {genErr, 1} +%% snmp_mgr:s([{[fStatus2, 1], 4}, {[fname2,0], "xfail"}]). -> {genErr, 2} + + +fname4(get) -> + {value, none}. + + +ftab2(_) -> + ok. + + +%% Following 2 clauses is for OTP-1222 +ftab2(is_set_ok, [1], _Cols) -> + % bad column - In: col 2 & 3 + io:format("** Here comes Error Report is_set_ok bad column~n"), + {inconsistentValue, 1}; +ftab2(is_set_ok, _, _Cols) -> + {noError, 0}; + +ftab2(set, [2], _Cols) -> + % bad column - In: col 2 & 3 + io:format("** Here comes Error Report set bad column~n"), + {commitFailed, 4}; +ftab2(set, _, _Cols) -> + {noError, 0}; + +%% Unfortunatly we can't force the undo - we don't know which var +%% is tried first. +%ftab2(undo, [3], Cols) -> +% % bad column - In: col 2 & 3 +% io:format("** Here comes (no Error Report) undo bad column~n"), +% {undoFailed, 5}; +%ftab2(undo, _, Cols) -> +% {noError, 0}; + +ftab2(get, [4], _Cols) -> + % bad return value + io:format("** Here comes Error Report get 1 bad return~n"), + []; +ftab2(get, [5], _Cols) -> + % bad return value + io:format("** Here comes Error Report get 2 bad return~n"), + [{value, 1}]; +ftab2(get, [6], _Cols) -> + % bad return value + io:format("** Here comes Error Report get 3 bad return~n"), + [{value,1},{value,2},{value,3}]; + +ftab2(get_next, [7], _Cols) -> + % bad return value + io:format("** Here comes Error Report get_next 1 bad return~n"), + []; +ftab2(get_next, [8], _Cols) -> + % bad return value + io:format("** Here comes Error Report get_next 2 bad return~n"), + [endOfTable]; +ftab2(get_next, [9], _Cols) -> + % bad return value + io:format("** Here comes Error Report get_next 3 bad return~n"), + [{[1,5],1},{[2,5],3},{[2,6],3}]. diff --git a/lib/snmp/test/modules.mk b/lib/snmp/test/modules.mk new file mode 100644 index 0000000000..ff848cad1b --- /dev/null +++ b/lib/snmp/test/modules.mk @@ -0,0 +1,76 @@ +#-*-makefile-*- ; force emacs to enter makefile-mode + +# %CopyrightBegin% +# +# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# +# The contents of this file are subject to the Erlang Public License, +# Version 1.1, (the "License"); you may not use this file except in +# compliance with the License. You should have received a copy of the +# Erlang Public License along with this software. If not, it can be +# retrieved online at http://www.erlang.org/. +# +# Software distributed under the License is distributed on an "AS IS" +# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +# the License for the specific language governing rights and limitations +# under the License. +# +# %CopyrightEnd% + +SUITE_MODULES = \ + snmp_SUITE \ + snmp_app_test \ + snmp_appup_test \ + snmp_compiler_test \ + snmp_conf_test \ + snmp_log_test \ + snmp_note_store_test \ + snmp_pdus_test \ + snmp_agent_mibs_test \ + snmp_agent_nfilter_test \ + snmp_agent_test \ + snmp_agent_test_lib \ + snmp_manager_config_test \ + snmp_manager_user \ + snmp_manager_user_old \ + snmp_manager_user_test \ + snmp_manager_user_test_lib \ + snmp_manager_test + +TEST_UTIL_MODULES = \ + snmp_test_lib \ + snmp_test_manager \ + snmp_test_mgr \ + snmp_test_mgr_misc \ + sa \ + klas3 \ + test1 \ + test2 + +TEST_SERVER_MODULES = \ + snmp_test_server \ + snmp_test_suite + +MODULES = \ + $(TEST_UTIL_MODULES) \ + $(SUITE_MODULES) + +HRL_FILES = snmp_test_lib.hrl + +MIB_FILES = \ + OLD-SNMPEA-MIB.mib \ + OLD-SNMPEA-MIB-v2.mib \ + Klas1.mib \ + Klas1-v2.mib \ + Klas2.mib \ + Klas3.mib \ + Klas4.mib \ + SA-MIB.mib \ + EX1-MIB.mib \ + TestTrap.mib \ + TestTrapv2.mib \ + Test1.mib \ + Test2.mib + +SPECS = snmp.spec snmp.spec.vxworks + diff --git a/lib/snmp/test/sa.erl b/lib/snmp/test/sa.erl new file mode 100644 index 0000000000..ad3ccce08f --- /dev/null +++ b/lib/snmp/test/sa.erl @@ -0,0 +1,44 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(sa). + +-compile(export_all). + +sa_bad_value(get) -> + {value, 3}. +sa_bad_value(is_set_ok, 5) -> + badValue; +sa_bad_value(is_set_ok, 6) -> + wrongValue. + +sa_gen_err(get) -> + {value, 4}. +sa_gen_err(set, _NewVal) -> + genErr. + +sa_too_big(get) -> + {value, [67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67,67]}. + + +sa_fel(get) -> + {value, undefined}. + + + diff --git a/lib/snmp/test/snmp.cover b/lib/snmp/test/snmp.cover new file mode 100644 index 0000000000..027dce68c1 --- /dev/null +++ b/lib/snmp/test/snmp.cover @@ -0,0 +1,15 @@ +%% -*- erlang -*- +{exclude, + [snmp_index, + snmpa_error_io, + snmpa_authentication_service, + snmpa_error_report, + snmpa_network_interface, + snmpa_network_interface_filter, + snmpa_notification_delivery_info_receiver, + snmpa_set_mechanism, + snmpm_network_interface, + snmpm_user + ] +}. + diff --git a/lib/snmp/test/snmp.spec b/lib/snmp/test/snmp.spec new file mode 100644 index 0000000000..0af52c139e --- /dev/null +++ b/lib/snmp/test/snmp.spec @@ -0,0 +1 @@ +{topcase, {dir, "../snmp_test"}}. diff --git a/lib/snmp/test/snmp.spec.vxworks b/lib/snmp/test/snmp.spec.vxworks new file mode 100644 index 0000000000..654aa96d8c --- /dev/null +++ b/lib/snmp/test/snmp.spec.vxworks @@ -0,0 +1,4 @@ +{topcase, {dir, "../snmp_test"}}. +{skip, {snmp_SUITE, test_v3, "Requires crypto"}}. + + diff --git a/lib/snmp/test/snmp_SUITE.erl b/lib/snmp/test/snmp_SUITE.erl new file mode 100644 index 0000000000..f560e36663 --- /dev/null +++ b/lib/snmp/test/snmp_SUITE.erl @@ -0,0 +1,157 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_SUITE). + +-export([all/1, + init_per_testcase/2, fin_per_testcase/2 + ]). + +-export([app/1, compiler/1, misc/1, agent/1, manager/1]). + +-export([ + app_test/1, + appup_test/1, + compiler_test/1, + conf_test/1, + pdus_test/1, + log_test/1, + note_store_test/1, + mibs_test/1, + nfilter_test/1, + agent_test/1, + manager_config_test/1, + manager_user_test/1, + manager_test/1 + ]). + +%% +%% ----- +%% + +init_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Config. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Top test case + +all(doc) -> + ["Test suites for the snmp application.", + "There are eight different sub test-suites."]; + +all(suite) -> + [ + app, + compiler, + misc, + agent, + manager + + ]. + +app(suite) -> + [ + app_test, + appup_test + ]. + +compiler(suite) -> + [ + compiler_test + ]. + +misc(suite) -> + [ + conf_test, + pdus_test, + log_test, + note_store_test + ]. + +agent(suite) -> + [ + mibs_test, + nfilter_test, + agent_test + ]. + +manager(suite) -> + [ + manager_config_test, + manager_user_test, + manager_test + ]. + + +app_test(suite) -> + [{snmp_app_test, all}]. + + +appup_test(suite) -> + [{snmp_appup_test, all}]. + + +compiler_test(suite) -> + [{snmp_compiler_test, all}]. + + +conf_test(suite) -> + [{snmp_conf_test, all}]. + + +pdus_test(suite) -> + [{snmp_pdus_test, all}]. + + +log_test(suite) -> + [{snmp_log_test, all}]. + + +note_store_test(suite) -> + [{snmp_note_store_test, all}]. + + +mibs_test(suite) -> + [{snmp_agent_mibs_test, all}]. + + +nfilter_test(suite) -> + [{snmp_agent_nfilter_test, all}]. + + +agent_test(suite) -> + [{snmp_agent_test, all}]. + + +manager_config_test(suite) -> + [{snmp_manager_config_test, all}]. + + +manager_user_test(suite) -> + [{snmp_manager_user_test, all}]. + + +manager_test(suite) -> + [{snmp_manager_test, all}]. + + diff --git a/lib/snmp/test/snmp_agent_bl_test.erl b/lib/snmp/test/snmp_agent_bl_test.erl new file mode 100644 index 0000000000..4608d90201 --- /dev/null +++ b/lib/snmp/test/snmp_agent_bl_test.erl @@ -0,0 +1,5654 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_agent_bl_test). + +%% TODO +%% * Test fault-tolerance (kill master etc) +%% + +% -include_lib("kernel/include/file.hrl"). +% -include("test_server.hrl"). +% -include("snmp_test_lib.hrl"). +% -define(SNMP_USE_V3, true). +% -include_lib("snmp/include/snmp_types.hrl"). + +%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl"). + + +% -define(klas1, [1,3,6,1,2,1,7]). +% -define(klas2, [1,3,6,1,2,1,9]). +% -define(klas3, [1,3,6,1,2,1,8,1]). +% -define(klas4, [1,3,6,1,2,1,8,4]). +% -define(sa, [1,3,6,1,4,1,193,2]). +% -define(system, [1,3,6,1,2,1,1]). +% -define(snmp, [1,3,6,1,2,1,11]). +% -define(snmpTraps, [1,3,6,1,6,3,1,1,5]). +% -define(ericsson, [1,3,6,1,4,1,193]). +% -define(testTrap, [1,3,6,1,2,1,15,0]). +% -define(xDescr, [1,3,6,1,2,1,17,1]). +% -define(xDescr2, [1,3,6,1,2,1,17,2]). + +% -define(active, 1). +% -define(notInService, 2). +% -define(notReady, 3). +% -define(createAndGo, 4). +% -define(createAndWait, 5). +% -define(destroy, 6). + +% -define(TRAP_UDP, 5000). + +% -define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"). + +-define(str(X), snmp_pdus:bits_to_str(X)). + +-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n", + [?LINE, self()]), + receive cont -> ok end + end). + + +-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]). +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + +-define(v1_2_3(V1,V2,V3), + case get(vsn) of + v1 -> V1; + v2 -> V2; + _ -> V3 + end). + +all(suite) -> {req, + [mnesia, distribution, + {local_slave_nodes, 2}, {time, 360}], + [{conf, init_all, cases(), finish_all}]}. + +init_per_testcase(_Case, Config) when list(Config) -> + Dog = ?t:timetrap(?t:minutes(6)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + Config. + +cases() -> + case ?OSTYPE() of + vxworks -> + %% No crypto app, so skip v3 testcases + [ + app_info, + test_v1, test_v2, test_v1_v2, + test_multi_threaded, + mib_storage, + tickets]; + _Else -> + [ + app_info, + test_v1, test_v2, test_v1_v2, test_v3, + test_multi_threaded, + mib_storage, + tickets + ] + end. + + +%%%----------------------------------------------------------------- +%%% The test case structure is as follows: +%%% +%%% init_all - starts mnesia, +%%% +%%% init_v1 - starts agent +%%% simple +%%% big - e.g. starts/stops subagent, load/unloads mibs +%%% init_mul +%%% mul_get +%%% mul_set +%%% <etc> +%%% finish_mul +%%% <etc> +%%% finish_v1 +%%% +%%% init_v2 - starts agent +%%% finish_v2 +%%% +%%% init_bilingual - starts agent +%%% finish_bilingual +%%% +%%% finish_all +%%% +%%% There is still one problem with these testsuites. If one test +%%% fails, it may not be possible to run some other cases, as it +%%% may have e.g. created some row or loaded some table, that it +%%% didn't undo (since it failed). +%%%----------------------------------------------------------------- + +init_all(Config0) when list(Config0) -> + ?LOG("init_all -> entry with" + "~n Config0: ~p",[Config0]), + + %% -- + %% Fix config: + %% + + DataDir0 = ?config(data_dir, Config0), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + Config1 = lists:keydelete(data_dir, 1, Config0), + Config = [{data_dir, DataDir3 ++ "/"}|Config1], + + %% -- + %% Start nodes + %% + + ?line {ok, SaNode} = start_node(snmp_sa), + ?line {ok, MgrNode} = start_node(snmp_mgr), + + + %% -- + %% Create necessary files + %% + + Dir = ?config(priv_dir, Config), + ?DBG("init_all -> Dir ~p", [Dir]), + + DataDir = ?config(data_dir, Config), + ?DBG("init_all -> DataDir ~p", [DataDir]), + + file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")), + ?DBG("init_all -> MgrDir ~p", [MgrDir]), + + file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")), + ?DBG("init_all -> AgentDir ~p", [AgentDir]), + + file:make_dir(SaDir = filename:join(Dir, "sa_dir/")), + ?DBG("init_all -> SaDir ~p", [SaDir]), + + + %% -- + %% Start and initiate mnesia + %% + + ?DBG("init_all -> load application mnesia", []), + ?line ok = application:load(mnesia), + + ?DBG("init_all -> load application mnesia on node ~p", [SaNode]), + ?line ok = rpc:call(SaNode, application, load, [mnesia]), + + ?DBG("init_all -> application mnesia: set_env dir",[]), + ?line application_controller:set_env(mnesia, dir, + filename:join(Dir, "Mnesia1")), + + ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]), + ?line rpc:call(SaNode, application_controller, set_env, + [mnesia, dir, filename:join(Dir, "Mnesia2")]), + + ?DBG("init_all -> create mnesia schema",[]), + ?line ok = mnesia:create_schema([SaNode, node()]), + + ?DBG("init_all -> start application mnesia",[]), + ?line ok = application:start(mnesia), + + ?DBG("init_all -> start application mnesia on ~p",[SaNode]), + ?line ok = rpc:call(SaNode, application, start, [mnesia]), + Ip = ?LOCALHOST(), + [{snmp_sa, SaNode}, + {snmp_mgr, MgrNode}, + {agent_dir, AgentDir ++ "/"}, + {mgr_dir, MgrDir ++ "/"}, + {sa_dir, SaDir ++ "/"}, + {mib_dir, DataDir}, + {ip, Ip} | + Config]. + +finish_all(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + stop_node(SaNode), + stop_node(MgrNode), + application:stop(mnesia). + +start_v1_agent(Config) when list(Config) -> + start_agent(Config, [v1]). + +start_v1_agent(Config,Opts) when list(Config), list(Opts) -> + start_agent(Config, [v1], Opts). + +start_v2_agent(Config) when list(Config) -> + start_agent(Config, [v2]). + +start_v3_agent(Config) when list(Config) -> + start_agent(Config, [v3]). + +start_bilingual_agent(Config) when list(Config) -> + start_agent(Config, [v1,v2]). + +start_multi_threaded_agent(Config) when list(Config) -> + start_agent(Config, [v2], [{snmp_multi_threaded, true}]). + +stop_agent(Config) when list(Config) -> + ?LOG("stop_agent -> entry with" + "~n Config: ~p",[Config]), + + {Sup, Par} = ?config(snmp_sup, Config), + ?DBG("stop_agent -> attempt to stop (sup) ~p" + "~n Sup: ~p" + "~n Par: ~p", + [Sup, + (catch process_info(Sup)), + (catch process_info(Par))]), + stop_sup(Sup, Par), + + {Sup2, Par2} = ?config(snmp_sub, Config), + ?DBG("stop_agent -> attempt to stop (sub) ~p" + "~n Sup2: ~p" + "~n Par2: ~p", + [Sup2, + (catch process_info(Sup2)), + (catch process_info(Par2))]), + stop_sup(Sup2, Par2), + + ?DBG("stop_agent -> done - now cleanup config", []), + C1 = lists:keydelete(snmp_sup, 1, Config), + lists:keydelete(snmp_sub, 1, C1). + + +stop_sup(Pid, _) when node(Pid) == node() -> + case (catch process_info(Pid)) of + PI when list(PI) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + exit(Pid, kill), + await_stopped(Pid, Ref); + {'EXIT', _Reason} -> + ?LOG("stop_sup -> ~p not running", [Pid]), + ok + end; +stop_sup(Pid, _) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + ?LOG("stop_sup -> Ref: ~p", [Ref]), + %% Pid ! {'EXIT', Parent, shutdown}, % usch + exit(Pid, kill), + await_stopped(Pid, Ref). + +await_stopped(Pid, Ref) -> + receive + {'DOWN', Ref, process, Pid, _Reason} -> + ?DBG("received down message for ~p", [Pid]), + ok + after 10000 -> + ?INF("await_stopped -> timeout for ~p",[Pid]), + erlang:demonitor(Ref), + ?FAIL({failed_stop,Pid}) + end. + + +start_agent(Config, Vsn) -> + start_agent(Config, Vsn, []). +start_agent(Config, Vsn, Opts) -> + ?LOG("start_agent -> entry (~p) with" + "~n Config: ~p" + "~n Vsn: ~p" + "~n Opts: ~p",[node(), Config, Vsn, Opts]), + + ?line AgentDir = ?config(agent_dir, Config), + ?line SaNode = ?config(snmp_sa, Config), + + snmp_app_env_init(vsn_init(Vsn) ++ + [{audit_trail_log, read_write_log}, + {audit_trail_log_dir, AgentDir}, + {audit_trail_log_size, {10240, 10}}, + {force_config_reload, false}, + {snmp_agent_type, master}, + {snmp_config_dir, AgentDir}, + {snmp_db_dir, AgentDir}, + {snmp_local_db_auto_repair, true}, + {snmp_master_agent_verbosity, trace}, + {snmp_supervisor_verbosity, trace}, + {snmp_mibserver_verbosity, trace}, + {snmp_symbolic_store_verbosity, trace}, + {snmp_note_store_verbosity, trace}, + {snmp_net_if_verbosity, trace}], + Opts), + + + process_flag(trap_exit,true), + + {ok, AppSup} = snmp_app_sup:start_link(), + unlink(AppSup), + ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]), + + ?DBG("start_agent -> start master agent (old style)",[]), + Sup = case (catch snmpa_app:start(normal)) of + {ok, S} -> + ?DBG("start_agent -> started, Sup: ~p",[S]), + S; + + Else -> + ?DBG("start_agent -> unknown result: ~n~p",[Else]), + %% Get info about the apps we depend on + MnesiaInfo = mnesia_running(), + ?FAIL({start_failed,Else,MnesiaInfo}) + end, + + ?DBG("start_agent -> unlink from supervisor",[]), + ?line unlink(Sup), + ?line SaDir = ?config(sa_dir, Config), + ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]), + ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]), + ?DBG("start_agent -> done",[]), + ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config]. + + +vsn_init(Vsn) -> + vsn_init([v1,v2,v3], Vsn, []). + +vsn_init([], _Vsn, Acc) -> + Acc; +vsn_init([V|Vsns], Vsn, Acc) -> + case lists:member(V, Vsn) of + true -> + vsn_init(Vsns, Vsn, [{V, true}|Acc]); + false -> + vsn_init(Vsns, Vsn, [{V, false}|Acc]) + end. + +snmp_app_env_init(Env0, Opts) -> + ?DBG("snmp_app_env_init -> unload snmp",[]), + ?line application:unload(snmp), + ?DBG("snmp_app_env_init -> load snmp",[]), + ?line application:load(snmp), + ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]), + F1 = fun({Key,Val} = New, Acc0) -> + ?DBG("snmp_app_env_init -> " + "updating setting ~p to ~p", [Key, Val]), + case lists:keyreplace(Key, 1, Acc0, New) of + Acc0 -> + [New|Acc0]; + Acc -> + Acc + end + end, + Env = lists:foldr(F1, Env0, Opts), + ?DBG("snmp_app_env_init -> Env: ~p",[Env]), + F2 = fun({Key,Val}) -> + ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]), + application_controller:set_env(snmp, Key, Val) + end, + lists:foreach(F2, Env). + + + + +%% Test if application is running +mnesia_running() -> ?IS_MNESIA_RUNNING(). +crypto_running() -> ?IS_CRYPTO_RUNNING(). + + +start_sub(Dir) -> + ?DBG("start_sub -> entry",[]), + Opts = [{db_dir, Dir}, + {supervisor, [{verbosity, trace}]}], + %% BMK BMK +% {ok, P} = snmp_supervisor:start_sub(Dir), + {ok, P} = snmpa_supervisor:start_sub_sup(Opts), + unlink(P), + {ok, {P, self()}}. + +create_tables(SaNode) -> + ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables}, + {attributes, [a1,a2]}]). + +delete_tables() -> + mnesia:delete_table(friendsTable2), + mnesia:delete_table(kompissTable2), + mnesia:delete_table(snmp_variables). + +%% Creation is done in runtime! +delete_mib_storage_mnesia_tables() -> + mnesia:delete_table(snmpa_mib_data), + mnesia:delete_table(snmpa_mib_tree), + mnesia:delete_table(snmpa_symbolic_store). + +%%----------------------------------------------------------------- +%% A test case is always one of: +%% - v1 specific case +%% - v2 specific case +%% - v1 and v2 case +%% All v1 specific cases are prefixed with v1_, and all v2 with +%% v2_. E.g. v1_trap/v2_trap. +%% +%% All other cases are shared. However, the testserver uses the name +%% of the case to generate a file for that case. The same case cannot +%% be used in different configurations in the same suite. Therefore +%% all these functions exists in two variants, the base function +%% <base>, and a second version <base>_2. There may be several +%% versions as well, <base>_N. +%%----------------------------------------------------------------- +mib_storage(suite) -> [ + mib_storage_ets, + mib_storage_dets, + mib_storage_mnesia, + mib_storage_size_check_ets, + mib_storage_size_check_dets, + mib_storage_size_check_mnesia, + mib_storage_varm_dets, + mib_storage_varm_mnesia + ]. + +mib_storage_ets(suite) -> {req, [], {conf, init_mib_storage_ets, + mib_storage_ets_cases(), + finish_mib_storage_ets}}. + +mib_storage_dets(suite) -> {req, [], {conf, init_mib_storage_dets, + mib_storage_dets_cases(), + finish_mib_storage_dets}}. + +mib_storage_mnesia(suite) -> {req, [], {conf, init_mib_storage_mnesia, + mib_storage_mnesia_cases(), + finish_mib_storage_mnesia}}. + +mib_storage_size_check_ets(suite) -> + {req, [], {conf, + init_size_check_mse, + mse_size_check_cases(), + finish_size_check_mse}}. + +mib_storage_size_check_dets(suite) -> + {req, [], {conf, + init_size_check_msd, + msd_size_check_cases(), + finish_size_check_msd}}. + +mib_storage_size_check_mnesia(suite) -> + {req, [], {conf, + init_size_check_msm, + msm_size_check_cases(), + finish_size_check_msm}}. + +mib_storage_varm_dets(suite) -> + {req, [], {conf, + init_varm_mib_storage_dets, + varm_mib_storage_dets_cases(), + finish_varm_mib_storage_dets}}. + +mib_storage_varm_mnesia(suite) -> + {req, [], {conf, + init_varm_mib_storage_mnesia, + varm_mib_storage_mnesia_cases(), + finish_varm_mib_storage_mnesia}}. + +mib_storage_ets_cases() -> + [ + mse_simple, + mse_v1_processing, + mse_big, + mse_big2, + mse_loop_mib, + mse_api, + mse_sa_register, + mse_v1_trap, + mse_sa_error, + mse_next_across_sa, + mse_undo, + mse_standard_mib, + mse_community_mib, + mse_framework_mib, + mse_target_mib, + mse_notification_mib, + mse_view_based_acm_mib, + mse_sparse_table, + mse_me_of, + mse_mib_of]. + +mib_storage_dets_cases() -> + [ + msd_simple, + msd_v1_processing, + msd_big, + msd_big2, + msd_loop_mib, + msd_api, + msd_sa_register, + msd_v1_trap, + msd_sa_error, + msd_next_across_sa, + msd_undo, + msd_standard_mib, + msd_community_mib, + msd_framework_mib, + msd_target_mib, + msd_notification_mib, + msd_view_based_acm_mib, + msd_sparse_table, + msd_me_of, + msd_mib_of + ]. + +mib_storage_mnesia_cases() -> + [ + msm_simple, + msm_v1_processing, + msm_big, + msm_big2, + msm_loop_mib, + msm_api, + msm_sa_register, + msm_v1_trap, + msm_sa_error, + msm_next_across_sa, + msm_undo, + msm_standard_mib, + msm_community_mib, + msm_framework_mib, + msm_target_mib, + msm_notification_mib, + msm_view_based_acm_mib, + msm_sparse_table, + msm_me_of, + msm_mib_of + ]. + +mse_size_check_cases() -> + [mse_size_check]. + +msd_size_check_cases() -> + [msd_size_check]. + +msm_size_check_cases() -> + [msm_size_check]. + +varm_mib_storage_dets_cases() -> + [msd_varm_mib_start]. + +varm_mib_storage_mnesia_cases() -> + [msm_varm_mib_start]. + +init_mib_storage_ets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,ets}, + init_ms(Config, [MibStorage]). + +init_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + init_ms(Config, [MibStorage]). + +init_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + init_ms(Config, [MibStorage]). + +init_ms(Config, Opts) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts], + [{vsn, v1} | start_v1_agent(Config,Opts1)]. + +init_size_check_mse(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, ets}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msd(Config) when list(Config) -> + AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage, {dets, AgentDir}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msm(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, {mnesia,[]}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_ms(Config, Opts) when list(Config) -> + SaNode = ?GCONF(snmp_sa, Config), + %% We are using v3 here, so crypto must be supported or else... + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + create_tables(SaNode), + AgentDir = ?GCONF(agent_dir, Config), + MgrDir = ?GCONF(mgr_dir, Config), + Ip = ?GCONF(ip, Config), + ?line ok = + config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_agent(Config, [v3], Opts)]. + +init_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_dets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +init_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_mnesia -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +finish_mib_storage_ets(Config) when list(Config) -> + ?LOG("finish_mib_storage_ets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_mib_storage_dets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_dets -> entry", []), + delete_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_size_check_mse(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msd(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msm(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_ms(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + + +%% These are just interface functions to fool the test server +mse_simple(X) -> simple(X). +mse_v1_processing(X) -> v1_processing(X). +mse_big(X) -> big(X). +mse_big2(X) -> big2(X). +mse_loop_mib(X) -> loop_mib(X). +mse_api(X) -> api(X). +mse_sa_register(X) -> sa_register(X). +mse_v1_trap(X) -> v1_trap(X). +mse_sa_error(X) -> sa_error(X). +mse_next_across_sa(X) -> next_across_sa(X). +mse_undo(X) -> undo(X). +mse_standard_mib(X) -> snmp_standard_mib(X). +mse_community_mib(X) -> snmp_community_mib(X). +mse_framework_mib(X) -> snmp_framework_mib(X). +mse_target_mib(X) -> snmp_target_mib(X). +mse_notification_mib(X) -> snmp_notification_mib(X). +mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +mse_sparse_table(X) -> sparse_table(X). +mse_me_of(X) -> ms_me_of(X). +mse_mib_of(X) -> ms_mib_of(X). + +msd_simple(X) -> simple(X). +msd_v1_processing(X) -> v1_processing(X). +msd_big(X) -> big(X). +msd_big2(X) -> big2(X). +msd_loop_mib(X) -> loop_mib(X). +msd_api(X) -> api(X). +msd_sa_register(X) -> sa_register(X). +msd_v1_trap(X) -> v1_trap(X). +msd_sa_error(X) -> sa_error(X). +msd_next_across_sa(X) -> next_across_sa(X). +msd_undo(X) -> undo(X). +msd_standard_mib(X) -> snmp_standard_mib(X). +msd_community_mib(X) -> snmp_community_mib(X). +msd_framework_mib(X) -> snmp_framework_mib(X). +msd_target_mib(X) -> snmp_target_mib(X). +msd_notification_mib(X) -> snmp_notification_mib(X). +msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msd_sparse_table(X) -> sparse_table(X). +msd_me_of(X) -> ms_me_of(X). +msd_mib_of(X) -> ms_mib_of(X). + +msm_simple(X) -> simple(X). +msm_v1_processing(X) -> v1_processing(X). +msm_big(X) -> big(X). +msm_big2(X) -> big2(X). +msm_loop_mib(X) -> loop_mib(X). +msm_api(X) -> api(X). +msm_sa_register(X) -> sa_register(X). +msm_v1_trap(X) -> v1_trap(X). +msm_sa_error(X) -> sa_error(X). +msm_next_across_sa(X) -> next_across_sa(X). +msm_undo(X) -> undo(X). +msm_standard_mib(X) -> snmp_standard_mib(X). +msm_community_mib(X) -> snmp_community_mib(X). +msm_framework_mib(X) -> snmp_framework_mib(X). +msm_target_mib(X) -> snmp_target_mib(X). +msm_notification_mib(X) -> snmp_notification_mib(X). +msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msm_sparse_table(X) -> sparse_table(X). +msm_me_of(X) -> ms_me_of(X). +msm_mib_of(X) -> ms_mib_of(X). + + +mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X). +msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X). +msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X). + +msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X). +msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X). + +ms_size_check(suite) -> []; +ms_size_check(Config) when list(Config) -> + p("ms_size_check..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?LOG("mib server size check...", []), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMPv2-MIB"), + ?line load_master_std("SNMPv2-TM"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMPv2-MIB"), + ?line unload_master("SNMPv2-TM"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + + +varm_mib_start(suite) -> []; +varm_mib_start(Config) when list(Config) -> + p("varm_mib_start..."), + ?LOG("varm_mib_start -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + %% Start the agent + Opts = ?GCONF(agent_opts, Config), + Config1 = start_v1_agent(Config, Opts), + + %% Sleep some in order for the agent to start properly + ?DBG("varm_mib_start -> sleep some (before loading mobs)", []), + ?SLEEP(5000), + + %% Load all the mibs + HardwiredMibs = loaded_mibs(), + ?DBG("varm_mib_start -> load all mibs", []), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + + %% Unload the hardwired mibs + ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []), + ?SLEEP(1000), + ?DBG("varm_mib_start -> unload (hardwired) mibs", []), + ?line unload_mibs(HardwiredMibs), %% unload hardwired + + ?DBG("varm_mib_start -> sleep some (before stopping agent)", []), + ?SLEEP(1000), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + Config2 = stop_agent(Config1), + + %% Sleep some in order for the agent to stop properly + ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []), + ?SLEEP(5000), + + %% Start the agent (again) + ?DBG("varm_mib_start -> start the agent", []), + Config3 = start_v1_agent(Config2, Opts), + + ?DBG("varm_mib_start -> sleep some (before starting tests)", []), + ?SLEEP(5000), + + %% Perform the test(s) + ?DBG("varm_mib_start -> perform the tests", []), + try_test(snmp_community_mib), + try_test(snmp_framework_mib), + try_test(snmp_target_mib), + try_test(snmp_notification_mib), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + stop_agent(Config3), + ok. + + +-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]). +-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]). +-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +ms_me_of(suite) -> []; +ms_me_of(Config) when list(Config) -> + p("ms_me_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = me_of(?snmpTrapCommunity_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = me_of(?vacmViewSpinLock_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +me_of(Oid) -> + case snmpa:me_of(Oid) of + {ok, #me{oid = Oid}} -> + ok; + {ok, #me{oid = OtherOid}} -> + case lists:reverse(Oid) of + [0|Rest] -> + case lists:reverse(Rest) of + OtherOid -> + ok; + AnotherOid -> + {error, {invalid_oid, Oid, AnotherOid}} + end; + _ -> + {error, {invalid_oid, Oid, OtherOid}} + end; + {error, Reason} -> + {error, Reason}; + Else -> + {error, Else} + end. + + +ms_mib_of(suite) -> []; +ms_mib_of(Config) when list(Config) -> + p("ms_mib_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance, + 'SNMP-USER-BASED-SM-MIB'), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +mib_of(Oid, ExpectedMibName) -> + ?DBG("mib_of -> entry with" + "~n Oid: ~p" + "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]), + %% case snmpa:mib_of(Oid) of + MibOf = snmpa:mib_of(Oid), + ?DBG("mib_of -> MibOf: ~n~p", [MibOf]), + case MibOf of + {ok, ExpectedMibName} -> + ok; + {ok, OtherMibName} -> + {error, {invalid_mib, ExpectedMibName, OtherMibName}}; + {error, Reason} -> + {error, Reason}; + Else -> + ?DBG("mib_of -> Else: ~n~p", [Else]), + {error, Else} + end. + + +app_info(suite) -> []; +app_info(Config) when list(Config) -> + SnmpDir = app_dir(snmp), + SslDir = app_dir(ssl), + CryptoDir = app_dir(crypto), + Attr = snmp:module_info(attributes), + AppVsn = + case lists:keysearch(app_vsn, 1, Attr) of + {value, {app_vsn, V}} -> + V; + false -> + "undefined" + end, + io:format("Root dir: ~s~n" + "SNMP: Application dir: ~s~n" + " Application ver: ~s~n" + "SSL: Application dir: ~s~n" + "CRYPTO: Application dir: ~s~n", + [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]), + ok. + +app_dir(App) -> + case code:lib_dir(App) of + D when list(D) -> + filename:basename(D); + {error, _Reason} -> + "undefined" + end. + + +test_v1(suite) -> {req, [], {conf, init_v1, v1_cases(), finish_v1}}. + +%v1_cases() -> [loop_mib]; +v1_cases() -> + [simple, + db_notify_client, + v1_processing, big, big2, loop_mib, + api, subagent, mnesia, multiple_reqs, + sa_register, v1_trap, sa_error, next_across_sa, undo, reported_bugs, + standard_mibs, sparse_table, cnt_64, + opaque, + % opaque]. + + change_target_addr_config]. + +init_v1(Config) when list(Config) -> + ?line SaNode = ?config(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v1} | start_v1_agent(Config)]. + +finish_v1(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v2(suite) -> {req, [], {conf, init_v2, v2_cases(), finish_v2}}. + +%v2_cases() -> [loop_mib_2]; +v2_cases() -> + [simple_2, v2_processing, big_2, big2_2, loop_mib_2, + api_2, subagent_2, mnesia_2, + multiple_reqs_2, sa_register_2, v2_trap, v2_inform, sa_error_2, + next_across_sa_2, undo_2, reported_bugs_2, standard_mibs_2, + v2_types, implied, sparse_table_2, cnt_64_2, opaque_2, v2_caps]. + +init_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_v2_agent(Config)]. + +finish_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v1_v2(suite) -> {req, [], {conf, init_v1_v2, v1_v2_cases(), finish_v1_v2}}. + +v1_v2_cases() -> + [simple_bi]. + +init_v1_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, bilingual} | start_bilingual_agent(Config)]. + +finish_v1_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v3(suite) -> {req, [], {conf, init_v3, v3_cases(), finish_v3}}. + +%v3_cases() -> [loop_mib_3]; +v3_cases() -> + [simple_3, v3_processing, + big_3, big2_3, api_3, subagent_3, mnesia_3, loop_mib_3, + multiple_reqs_3, sa_register_3, v3_trap, v3_inform, sa_error_3, + next_across_sa_3, undo_3, reported_bugs_3, standard_mibs_3, + v3_security, + v2_types_3, implied_3, sparse_table_3, cnt_64_3, opaque_3, v2_caps_3]. + +init_v3(Config) when list(Config) -> + %% Make sure crypto works, otherwise start_agent will fail + %% and we will be stuck with a bunch of mnesia tables for + %% the rest of this suite... + ?DBG("start_agent -> start crypto app",[]), + case os:type() of + vxworks -> + no_crypto; + _ -> + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end + end, + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v3], MgrDir, AgentDir, + tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_v3_agent(Config)]. + +finish_v3(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_multi_threaded(suite) -> {req, [], {conf, init_mt, mt_cases(), finish_mt}}. + +mt_cases() -> + [multi_threaded, mt_trap]. + +init_mt(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_multi_threaded_agent(Config)]. + +finish_mt(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +%% This one *must* be run first in each case. +init_case(Config) when list(Config) -> + ?DBG("init_case -> entry with" + "~n Config: ~p", [Config]), + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + MasterNode = node(), + + SaHost = ?HOSTNAME(SaNode), + MgrHost = ?HOSTNAME(MgrNode), + MasterHost = ?HOSTNAME(MasterNode), + {ok, MasterIP} = snmp_misc:ip(MasterHost), + {ok, MIP} = snmp_misc:ip(MgrHost), + {ok, SIP} = snmp_misc:ip(SaHost), + + + put(mgr_node, MgrNode), + put(sa_node, SaNode), + put(master_node, MasterNode), + put(sa_host, SaHost), + put(mgr_host, MgrHost), + put(master_host, MasterHost), + put(mip, tuple_to_list(MIP)), + put(masterip , tuple_to_list(MasterIP)), + put(sip, tuple_to_list(SIP)), + + MibDir = ?config(mib_dir, Config), + put(mib_dir, MibDir), + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + put(std_mib_dir, StdM), + + MgrDir = ?config(mgr_dir, Config), + put(mgr_dir, MgrDir), + + put(vsn, ?config(vsn, Config)), + ?DBG("init_case -> exit with" + "~n MasterNode: ~p" + "~n SaNode: ~p" + "~n MgrNode: ~p" + "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]), + {SaNode, MgrNode, MibDir}. + +load_master(Mib) -> + ?DBG("load_master -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]). + +load_master_std(Mib) -> + ?DBG("load_master_std -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]). + +unload_master(Mib) -> + ?DBG("unload_master -> entry with" + "~n Mib: ~p", [Mib]), + ok = snmpa:unload_mibs(snmp_master_agent, [Mib]). + +loaded_mibs() -> + ?DBG("loaded_mibs -> entry",[]), + Info = snmpa:info(snmp_master_agent), + {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info), + [atom_to_list(Mib) || {Mib,_,_} <- Mibs]. + +unload_mibs(Mibs) -> + ?DBG("unload_mibs -> entry with" + "~n Mibs: ~p", [Mibs]), + ok = snmpa:unload_mibs(snmp_master_agent, Mibs). + +start_subagent(SaNode, RegTree, Mib) -> + ?DBG("start_subagent -> entry with" + "~n SaNode: ~p" + "~n RegTree: ~p" + "~n Mib: ~p", [SaNode, RegTree, Mib]), + MA = whereis(snmp_master_agent), + ?DBG("start_subagent -> MA: ~p", [MA]), + MibDir = get(mib_dir), + Mib1 = join(MibDir,Mib), + %% BMK BMK +% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of + case rpc:call(SaNode, snmpa_supervisor, + start_sub_agent, [MA, RegTree, [Mib1]]) of + {ok, SA} -> + ?DBG("start_subagent -> SA: ~p", [SA]), + {ok, SA}; + Error -> + ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]}) + end. + +stop_subagent(SA) -> + ?DBG("stop_subagent -> entry with" + "~n SA: ~p", [SA]), + %% BNK BMK + %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]). + rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]). + +%%----------------------------------------------------------------- +%% This function takes care of the old OTP-SNMPEA-MIB. +%% Unfortunately, the testcases were written to use the data in the +%% internal tables, and these table are now obsolete and not used +%% by the agent. Therefore, we emulate them by using +%% OLD-SNMPEA-MIB, which uses the default impl. of all tables. +%% +%% These two rows must exist in intCommunityTable +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. +%% (But with the manager's IP address) +%% +%%----------------------------------------------------------------- +init_old() -> + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [6 | "public"], + {get(mip), "public", 2, 2}), + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [13 | "standard trap"], + {get(mip), "standard trap", 2, 1}), + snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]). + + + +simple(suite) -> []; +simple(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(simple_standard_test). + +simple_2(X) -> simple(X). + +simple_bi(suite) -> []; +simple_bi(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(vsn, v1), % First, try v1 manager + try_test(simple_standard_test), + + put(vsn, v2), % Then, try v2 manager + try_test(simple_standard_test). + +simple_3(X) -> + simple(X). + +big(suite) -> []; +big(Config) when list(Config) -> + ?DBG("big -> entry", []), + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?DBG("big -> SA: ~p", [SA]), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB"). + +big_2(X) -> big(X). + +big_3(X) -> big(X). + + +big2(suite) -> []; +big2(Config) when list(Config) -> + %% This is exactly the same tests as 'big', but with the + %% v2 equivalent of the mibs. + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"), + ?line load_master("OLD-SNMPEA-MIB-v2"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB-v2"). + +big2_2(X) -> big2(X). + +big2_3(X) -> big2(X). + + +multi_threaded(suite) -> []; +multi_threaded(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(multi_threaded_test), + ?line unload_master("Test1"). + +mt_trap(suite) -> []; +mt_trap(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + ?line load_master("TestTrapv2"), + try_test(mt_trap_test, [MA]), + ?line unload_master("TestTrapv2"), + ?line unload_master("Test1"). + +v2_types(suite) -> []; +v2_types(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(types_v2_test), + ?line unload_master("Test1"). + +v2_types_3(X) -> v2_types(X). + + +implied(suite) -> []; +implied(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(implied_test,[MA]), + ?line unload_master("Test1"). + +implied_3(X) -> implied(X). + + +sparse_table(suite) -> []; +sparse_table(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(sparse_table_test), + ?line unload_master("Test1"). + +sparse_table_2(X) -> sparse_table(X). + +sparse_table_3(X) -> sparse_table(X). + +cnt_64(suite) -> []; +cnt_64(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(cnt_64_test, [MA]), + ?line unload_master("Test1"). + +cnt_64_2(X) -> cnt_64(X). + +cnt_64_3(X) -> cnt_64(X). + +opaque(suite) -> []; +opaque(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(opaque_test), + ?line unload_master("Test1"). + +opaque_2(X) -> opaque(X). + +opaque_3(X) -> opaque(X). + + +change_target_addr_config(suite) -> []; +change_target_addr_config(Config) when list(Config) -> + p("Testing changing target address config..."), + ?LOG("change_target_addr_config -> entry",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(sname,snmp_suite), + put(verbosity,trace), + + MA = whereis(snmp_master_agent), + + ?LOG("change_target_addr_config -> load TestTrap",[]), + ?line load_master("TestTrap"), + + ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,trace), + + %% First send some traps that will arive att the original manager + ?LOG("change_target_addr_config -> send trap",[]), + try_test(ma_trap1, [MA]), + + ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,silence), + + %% Start new dummy listener + ?LOG("change_target_addr_config -> start dummy manager",[]), + ?line {ok,Pid,NewPort} = dummy_manager_start(MA), + + %% Reconfigure + ?LOG("change_target_addr_config -> reconfigure",[]), + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_addr_conf(AgentDir, NewPort), + ?line snmp_target_mib:reconfigure(AgentDir), + + %% Send the trap again + ?LOG("change_target_addr_config -> send trap again",[]), + catch dummy_manager_send_trap2(Pid), + + ?LOG("change_target_addr_config -> await trap ack",[]), + catch dummy_manager_await_trap2_ack(), + + ?LOG("change_target_addr_config -> stop dummy manager",[]), + ?line ok = dummy_manager_stop(Pid), + + ?LOG("change_target_addr_config -> reset target address config",[]), + ?line reset_target_addr_conf(AgentDir), + + ?LOG("change_target_addr_config -> unload TestTrap",[]), + ?line unload_master("TestTrap"). + + +dummy_manager_start(MA) -> + ?DBG("dummy_manager_start -> entry",[]), + Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]), + ?DBG("dummy_manager_start -> Pid: ~p",[Pid]), + await_dummy_manager_started(Pid). + +await_dummy_manager_started(Pid) -> + receive + {dummy_manager_started,Pid,Port} -> + ?DBG("dummy_manager_start -> acknowledge received with" + "~n Port: ~p",[Port]), + {ok,Pid,Port}; + {'EXIT', Pid, Reason} -> + {error, Pid, Reason}; + O -> + ?LOG("dummy_manager_start -> received unknown message:" + "~n ~p",[O]), + await_dummy_manager_started(Pid) + end. + +dummy_manager_stop(Pid) -> + ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]), + Pid ! stop, + receive + {dummy_manager_stopping, Pid} -> + ?DBG("dummy_manager_stop -> acknowledge received",[]), + ok + after 10000 -> + ?ERR("dummy_manager_stop -> timeout",[]), + timeout + end. + +dummy_manager_send_trap2(Pid) -> + ?DBG("dummy_manager_send_trap2 -> entry",[]), + Pid ! {send_trap,testTrap2}. + +dummy_manager_await_trap2_ack() -> + ?DBG("dummy_manager_await_trap2 -> entry",[]), + receive + {received_trap,Trap} -> + ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]), + %% Note: + %% Without this sleep the v2_inform_i testcase failes! There + %% is no relation between these two test cases as far as I + %% able to figure out... + sleep(60000), + ok; + O -> + ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]), + ok + after 10000 -> + ?ERR("dummy_manager_await_trap2 -> timeout",[]), + timeout + end. + +dummy_manager_init(Parent,MA) -> + ?DBG("dummy_manager_init -> entry with" + "~n Parent: ~p" + "~n MA: ~p",[Parent,MA]), + {ok,S} = gen_udp:open(0,[{recbuf,65535}]), + ?DBG("dummy_manager_init -> S: ~p",[S]), + {ok,Port} = inet:port(S), + ?DBG("dummy_manager_init -> Port: ~p",[Port]), + Parent ! {dummy_manager_started,self(),Port}, + dummy_manager_loop(Parent,S,MA). + +dummy_manager_loop(P,S,MA) -> + ?LOG("dummy_manager_loop -> ready for receive",[]), + receive + {send_trap,Trap} -> + ?LOG("dummy_manager_loop -> received trap send request" + "~n Trap: ~p",[Trap]), + snmpa:send_trap(MA, Trap, "standard trap"), + dummy_manager_loop(P,S,MA); + {udp, _UdpId, Ip, UdpPort, Bytes} -> + ?LOG("dummy_manager_loop -> received upd message" + "~n from: ~p:~p" + "~n size: ~p", + [Ip, UdpPort, dummy_manager_message_sz(Bytes)]), + R = dummy_manager_handle_message(Bytes), + ?DBG("dummy_manager_loop -> R: ~p",[R]), + P ! R, + dummy_manager_loop(P,S,MA); + stop -> + ?DBG("dummy_manager_loop -> received stop request",[]), + P ! {dummy_manager_stopping, self()}, + gen_udp:close(S), + exit(normal); + O -> + ?LOG("dummy_manager_loop -> received unknown message:" + "~n ~p",[O]), + dummy_manager_loop(P,S,MA) + end. + +dummy_manager_message_sz(B) when binary(B) -> + size(B); +dummy_manager_message_sz(L) when list(L) -> + length(L); +dummy_manager_message_sz(_) -> + undefined. + +dummy_manager_handle_message(Bytes) -> + case (catch snmp_pdus:dec_message(Bytes)) of + {'EXIT',Reason} -> + ?ERR("dummy_manager_handle_message -> " + "failed decoding message only:~n ~p",[Reason]), + {error,Reason}; + M -> + ?DBG("dummy_manager_handle_message -> decoded message:" + "~n ~p",[M]), + {received_trap,M} + end. + + +api(suite) -> []; +api(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(api_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +api_2(X) -> api(X). + +api_3(X) -> api(X). + + +subagent(suite) -> []; +subagent(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + try_test(load_test_sa), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + + p("Loading previous subagent mib in master and testing..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]), + try_test(load_test), + + p("Unloading previous subagent mib in master and testing..."), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]), + try_test(unreg_test), + p("Testing register subagent..."), + rpc:call(SaNode, snmp, register_subagent, + [MA, ?klas1, SA]), + try_test(load_test_sa), + + ?line stop_subagent(SA), + try_test(unreg_test). + +subagent_2(X) -> subagent(X). + +subagent_3(X) -> subagent(X). + + +mnesia(suite) -> []; +mnesia(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent with mnesia impl..."), + {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + try_test(big_test_2), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA). + +mnesia_2(X) -> mnesia(X). + +mnesia_3(X) -> mnesia(X). + + +multiple_reqs(suite) -> + {req, [], {conf, init_mul, mul_cases(), finish_mul}}. + +mul_cases() -> + [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err]. + +multiple_reqs_2(suite) -> + {req, [], {conf, init_mul, mul_cases_2(), finish_mul}}. + +multiple_reqs_3(_X) -> + {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}. + + +mul_cases_2() -> + [mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2, mul_set_err_2]. + + +mul_cases_3() -> + [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3]. + + +init_mul(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + [{mul_sub, SA} | Config]. + +finish_mul(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + SA = ?config(mul_sub, Config), + + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA), + lists:keydelete(mul_sub, 1, Config). + +mul_get(suite) -> []; +mul_get(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get..."), + try_test(do_mul_get). + +mul_get_2(X) -> mul_get(X). + +mul_get_3(X) -> mul_get(X). + + +mul_get_err(suite) -> []; +mul_get_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get with error..."), + try_test(do_mul_get_err). + +mul_get_err_2(X) -> mul_get_err(X). + +mul_get_err_3(X) -> mul_get_err(X). + + +mul_next(suite) -> []; +mul_next(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next). + +mul_next_2(X) -> mul_next(X). + +mul_next_3(X) -> mul_next(X). + + +mul_next_err(suite) -> []; +mul_next_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next_err). + +mul_next_err_2(X) -> mul_next_err(X). + +mul_next_err_3(X) -> mul_next_err(X). + + +mul_set(suite) -> []; +mul_set(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set..."), + try_test(do_mul_set). + +mul_set_2(X) -> mul_set(X). + +mul_set_3(X) -> mul_set(X). + + +mul_set_err(suite) -> []; +mul_set_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set with error..."), + try_test(do_mul_set_err). + +mul_set_err_2(X) -> mul_set_err(X). + +mul_set_err_3(X) -> mul_set_err(X). + + +sa_register(suite) -> []; +sa_register(Config) when list(Config) -> + ?DBG("sa_register -> entry", []), + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?DBG("sa_register -> start subagent", []), + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + + ?DBG("sa_register -> unregister subagent", []), + p("Testing unregister subagent (2)..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Loading SA-MIB..."), + ?DBG("sa_register -> unload mibs", []), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + ?DBG("sa_register -> unload mibs", []), + snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]), + ?DBG("sa_register -> register subagent", []), + rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]), + try_test(sa_mib), + + ?DBG("sa_register -> stop subagent", []), + ?line stop_subagent(SA). + +sa_register_2(X) -> sa_register(X). + +sa_register_3(X) -> sa_register(X). + + +v1_trap(suite) -> []; +v1_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_trap1, [MA]), + try_test(ma_trap2, [MA]), + try_test(ma_v2_2_v1_trap, [MA]), + try_test(ma_v2_2_v1_trap2, [MA]), + + p("Testing trap sending from subagent..."), + try_test(sa_trap1, [SA]), + try_test(sa_trap2, [SA]), + try_test(sa_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v2_trap(suite) -> []; +v2_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + + try_test(ma_v2_trap1, [MA]), + try_test(ma_v2_trap2, [MA]), + try_test(ma_v1_2_v2_trap, [MA]), + try_test(ma_v1_2_v2_trap2, [MA]), + + try_test(sa_mib), + p("Testing trap sending from subagent..."), + try_test(sa_v1_2_v2_trap1, [SA]), + try_test(sa_v1_2_v2_trap2, [SA]), + try_test(sa_v1_2_v2_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v3_trap(X) -> + v2_trap(X). + +v2_inform(suite) -> + {req, [], {conf, init_v2_inform, [v2_inform_i], finish_v2_inform}}. + +v3_inform(_X) -> + %% v2_inform(X). + {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}. + +init_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +init_v3_inform(X) -> + init_v2_inform(X). + +finish_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +finish_v3_inform(X) -> + finish_v2_inform(X). + + + +v2_inform_i(suite) -> []; +v2_inform_i(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing inform sending from master agent... NOTE! This test\ntakes a " + "few minutes (5) to complete."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_v2_inform1, [MA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"). + +v3_inform_i(X) -> v2_inform_i(X). + + +sa_error(suite) -> []; +sa_error(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing sa bad value (is_set_ok)..."), + try_test(sa_errs_bad_value), + + p("Testing sa gen err (set)..."), + try_test(sa_errs_gen_err), + + p("Testing too big..."), + try_test(sa_too_big), + + ?line unload_master("OLD-SNMPEA-MIB"), + stop_subagent(SA). + +sa_error_2(X) -> sa_error(X). + +sa_error_3(X) -> sa_error(X). + + +next_across_sa(suite) -> []; +next_across_sa(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Loading another subagent mib..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]), + + rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]), + try_test(load_test_sa), + + p("Testing next across subagent (endOfMibView from SA)..."), + try_test(next_across_sa), + + p("Unloading mib"), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Starting another subagent"), + ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"), + p("Testing next across subagent (wrong prefix from SA)..."), + try_test(next_across_sa), + + stop_subagent(SA), + stop_subagent(SA2). + +next_across_sa_2(X) -> next_across_sa(X). + +next_across_sa_3(X) -> next_across_sa(X). + + +undo(suite) -> []; +undo(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing undo phase at master agent..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]), + try_test(undo_test), + try_test(api_test2), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]), + + p("Testing bad return values from instrum. funcs..."), + try_test(bad_return), + + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]), + + p("Testing undo phase at subagent..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]), + ?line ok = snmpa:register_subagent(MA, ?klas3, SA), + ?line ok = snmpa:register_subagent(MA, ?klas4, SA), + try_test(undo_test), + try_test(api_test3), + + p("Testing undo phase across master/subagents..."), + try_test(undo_test), + try_test(api_test3), + stop_subagent(SA). + +undo_2(X) -> undo(X). + +undo_3(X) -> undo(X). + +%% Req. Test2 +v1_processing(suite) -> []; +v1_processing(Config) when list(Config) -> + ?DBG("v1_processing -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v1_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v2_processing(suite) -> []; +v2_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v3_processing(suite) -> []; +v3_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), % same as v2! + ?line unload_master("Test2"). + + +%% We'll try get/set/trap and inform for all the auth & priv protocols. +%% For informs, the mgr is auth-engine. The agent has to sync. This is +%% accomplished by the first inform sent. That one will generate a +%% report, which makes it in sync. The notification-generating +%% application times out, and send again. This time it'll work. +v3_security(suite) -> [v3_crypto_basic, v3_md5_auth, v3_sha_auth, v3_des_priv]. + +v3_crypto_basic(suite) -> []; +v3_crypto_basic(_Config) -> + EID = [0,0,0,0,0,0,0,0,0,0,0,2], + %% From rfc2274 appendix A.3.1 + ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID), + ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f, + 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] = + KMd5_1, + %% From rfc2274 appendix A.3.2 + ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID), + ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23, + 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] = + KSHA_1, + %% From rfc2274, appendix A.5.1 + ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9, + 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] = + snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + %% From rfc2274, appendix A.5.2 + ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4, + 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db, + 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + KSHA_1t = lists:sublist(KSHA_1, 16), + KSHA_2t = lists:sublist(KSHA_2, 16), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b, + 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + + %% Try with correct random + ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2), + ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1), + ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2), + ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2), + ok. + + + +v3_md5_auth(suite) -> []; +v3_md5_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing MD5 authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authMD5"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_sha_auth(suite) -> []; +v3_sha_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing SHA authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authSHA"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_des_priv(suite) -> []; +v3_des_priv(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing DES encryption...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +%% Make sure mgr is in sync with agent +v3_sync(Funcs) -> + ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]), + g([[sysDescr, 0]]), + expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]), + g([[sysDescr, 0]]), + expect(433, [{[sysDescr,0], any}]), + lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs). + +v3_inform_sync(MA) -> + ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, + "standard inform", []), + %% Make sure agent is in sync with mgr... + ?DBG("v3_sync -> wait some time: ",[]), + sleep(20000), % more than 1500*10 in target_addr.conf + ?DBG("v3_sync -> await response",[]), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]). + + +v2_caps(suite) -> []; +v2_caps(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(v2_caps_i, [node()]). + +v2_caps_3(X) -> v2_caps(X). + + +v2_caps_i(Node) -> + ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]), + g([[sysORID, Idx], [sysORDescr, Idx]]), + ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]}, + {[sysORDescr, Idx], "test cap"}]), + ?line rpc:call(Node, snmp, del_agent_caps, [Idx]), + g([[sysORID, Idx]]), + ?line expect(2, [{[sysORID, Idx], noSuchInstance}]). + + +%% Req. Test2 +v1_proc() -> + ?DBG("v1_proc -> entry", []), + %% According to RFC1157. + %% Template: <Section>:<list no> + v1_get_p(), + v1_get_next_p(), + v1_set_p(). + + +v1_get_p() -> + %% 4.1.2:1 + g([[test2]]), + ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]), + g([[tDescr]]), + ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]), + g([[tDescr2,0]]), + ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]), + g([[tDescr3,0]]), + ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]), + g([[tDescr4,0]]), + ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'}, + {[tDescr,0], 'NULL'}]), + g([[sysDescr,3]]), + ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]), + + %% 4.1.2:2 + g([[tTable]]), + ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]), + g([[tEntry]]), + ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]), + + %% 4.1.2:3 + g([[tTooBig, 0]]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.2:4 + g([[tGenErr1, 0]]), + ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]). + + +v1_get_next_p() -> + %% 4.1.3:1 + gn([[1,3,7,1]]), + ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]), + gn([[tDescr2]]), + ?line expect(11, tooBig, 0, any), + + %% 4.1.3:2 + gn([[tTooBig]]), + io:format("We currently don't handle tooBig correct!!!\n"), +% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]), + ?line expect(20, tooBig, 0, any), + + %% 4.1.3:3 + gn([[tGenErr1]]), +% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]), + ?line expect(40, genErr, 1, any), + gn([[tGenErr2]]), +% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]), + ?line expect(41, genErr, 1, any), + gn([[sysDescr], [tGenErr3]]), +% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'}, +% {[tGenErr3], 'NULL'}]). + ?line expect(42, genErr, 2, any). + +v1_set_p() -> + %% 4.1.5:1 + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]), + s([{[tDescr3], s, "noSuchObject"}]), + ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]), + s([{[tDescr3,1], s, "noSuchInstance"}]), + ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]), + s([{[tDescr2,0], s, "inconsistentName"}]), + ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]), + + %% 4.1.5:2 + s([{[tDescr2, 0], i, 4}]), + ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.1.5:3 + %% The standard is quite incorrect here. The resp pdu was too big. In + %% the resp pdu, we have the original vbs. In the tooBig pdu we still + %% have to original vbs => the tooBig pdu is too big as well!!! It + %% may not get it to the manager, unless the agent uses 'NULL' instead + %% of the std-like original value. + s([{[tTooBig, 0], s, ?tooBigStr}]), + %% according to std: +% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.5:4 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]), + s([{[tDescr2, 0], s, "commit_fail"}]), + ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]). + +%% Req. Test2 +v2_proc() -> + %% According to RFC1905. + %% Template: <Section>:<list no> + ?DBG("v2_proc -> entry",[]), + v2_get_p(), + v2_get_next_p(), + v2_get_bulk_p(), + v2_set_p(). + +v2_get_p() -> + %% 4.2.1:2 + ?DBG("v2_get_p -> entry",[]), + g([[test2]]), + ?line expect(10, [{[test2], noSuchObject}]), + g([[tDescr]]), + ?line expect(11, [{[tDescr], noSuchObject}]), + g([[tDescr4,0]]), + ?line expect(12, [{[tDescr4,0], noSuchObject}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}, + {[tDescr,0], noSuchObject}]), + g([[tTable]]), + ?line expect(14, [{[tTable], noSuchObject}]), + g([[tEntry]]), + ?line expect(15, [{[tEntry], noSuchObject}]), + + %% 4.2.1:3 + g([[tDescr2,0]]), %% instrum ret noSuchName!!! + ?line expect(20, [{[tDescr2,0], noSuchInstance}]), + g([[tDescr3,0]]), + ?line expect(21, [{[tDescr3,0], noSuchInstance}]), + g([[sysDescr,3]]), + ?line expect(22, [{[sysDescr, 3], noSuchInstance}]), + g([[tIndex,1]]), + ?line expect(23, [{[tIndex, 1], noSuchInstance}]), + + %% 4.2.1 - any other error: genErr + g([[tGenErr1, 0]]), + ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]), + + %% 4.2.1 - tooBig + g([[tTooBig, 0]]), + ?line expect(40, tooBig, 0, []). + + +v2_get_next_p() -> + %% 4.2.2:2 + ?DBG("v2_get_next_p -> entry",[]), + gn([[1,3,7,1]]), + ?line expect(10, [{[1,3,7,1], endOfMibView}]), + gn([[sysDescr], [1,3,7,1]]), + ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gn([[tCnt2, 1]]), + ?line expect(12, [{[tCnt2,2], 100}]), + gn([[tCnt2, 2]]), + ?line expect(12, [{[tCnt2,2], endOfMibView}]), + + %% 4.2.2 - any other error: genErr + gn([[tGenErr1]]), + ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]), + gn([[tGenErr2]]), + ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]), + gn([[sysDescr], [tGenErr3]]), + ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'}, + {[tGenErr3], 'NULL'}]), + + %% 4.2.2 - tooBig + gn([[tTooBig]]), + ?line expect(20, tooBig, 0, []). + +v2_get_bulk_p() -> + %% 4.2.3 + ?DBG("v2_get_bulk_p -> entry",[]), + gb(1, 1, []), + ?line expect(10, []), + gb(-1, 1, []), + ?line expect(11, []), + gb(-1, -1, []), + ?line expect(12, []), + gb(-1, -1, []), + ?line expect(13, []), + gb(2, 0, [[sysDescr], [1,3,7,1]]), + ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(1, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(0, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]), + ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]), + ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[sysDescr, 0], "Erlang SNMP agent"}]), + + gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig. + ?line expect(19, []), + + gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]), + ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'}, + {[sysObjectID], 'NULL'}, + {[tGenErr1], 'NULL'}, + {[sysDescr], 'NULL'}]), + gb(0, 2, [[tCnt2, 1]]), + ?line expect(21, [{[tCnt2,2], 100}, + {[tCnt2,2], endOfMibView}]). + + +v2_set_p() -> + %% 4.2.5:1 + ?DBG("v2_set_p -> entry",[]), + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]), + + %% 4.2.5:2 + s([{[1,3,6,1,0], s, "noSuchObject"}]), + ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]), + + %% 4.2.5:3 + s([{[tDescr2, 0], i, 4}]), + ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.2.5:4 + s([{[tStr, 0], s, ""}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]), + s([{[tStr, 0], s, "12345"}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]), + + %% 4.2.5:5 - N/A + + %% 4.2.5:6 + s([{[tInt1, 0], i, 0}]), + ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]), + s([{[tInt1, 0], i, 5}]), + ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]), + s([{[tInt2, 0], i, 0}]), + ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]), + s([{[tInt2, 0], i, 5}]), + ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]), + s([{[tInt3, 0], i, 5}]), + ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]), + + %% 4.2.5:7 + s([{[tDescrX, 1, 1], s, "noCreation"}]), + ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]), + + %% 4.2.5:8 + s([{[tDescrX, 1, 2], s, "inconsistentName"}]), + ?line expect(80, inconsistentName, 1, + [{[tDescrX, 1, 2], "inconsistentName"}]), + + %% 4.2.5:9 + s([{[tCnt, 1, 2], i, 5}]), + ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]), + + %% 4.2.5:10 + s([{[tDescr2,0], s, "inconsistentValue"}]), + ?line expect(100, inconsistentValue, 1, + [{[tDescr2,0], "inconsistentValue"}]), + + %% 4.2.5:11 + s([{[tDescr2,0], s, "resourceUnavailable"}]), + ?line expect(110, resourceUnavailable, 1, + [{[tDescr2,0],"resourceUnavailable"}]), + + %% 4.2.5:12 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]). + + %% commitFailed and undoFailed is tested by the 'undo' case. + + +%% Req. OLD-SNMPEA-MIB +table_test() -> + io:format("Testing simple get, next and set on communityTable...~n"), +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. + Key1c3 = [intCommunityViewIndex,get(mip),is("public")], + Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")], + Key1c4 = [intCommunityAccess,get(mip),is("public")], + EndKey = [intCommunityEntry,[9],get(mip),is("public")], + gn([[intCommunityEntry]]), + ?line expect(7, [{Key1c3, 2}]), + gn([[intCommunityTable]]), + ?line expect(71, [{Key1c3, 2}]), + gn([[community]]), + ?line expect(72, [{Key1c3, 2}]), + gn([[otpSnmpeaMIB]]), + ?line expect(73, [{Key1c3, 2}]), + gn([[ericsson]]), + ?line expect(74, [{Key1c3, 2}]), + gn([Key1c3]), + ?line expect(8, [{Key2c3, 2}]), + gn([Key2c3]), + ?line expect(9, [{Key1c4, 2}]), + gn([EndKey]), + AgentIp = [intAgentIpAddress,0], + ?line expect(10, [{AgentIp, any}]), + g([Key1c3]), + ?line expect(11, [{Key1c3, 2}]), + g([EndKey]), + ?line ?v1_2(expect(12, noSuchName, 1, any), + expect(12, [{EndKey, noSuchObject}])), + + io:format("Testing row creation/deletion on communityTable...~n"), + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + s([{NewKeyc5, ?createAndGo}]), + ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any), + s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]), + ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]), + g([NewKeyc4]), + ?line expect(16, [{NewKeyc4, 2}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(17, [{NewKeyc5, ?destroy}]), + s([{NewKeyc4, 2}]), + ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]), + s([{NewKeyc5, ?createAndWait}]), + ?line expect(19, [{NewKeyc5, ?createAndWait}]), + g([NewKeyc5]), + ?line expect(20, [{NewKeyc5, ?notReady}]), + s([{NewKeyc4, 2}]), + ?line expect(21, [{NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(22, [{NewKeyc5, ?notReady}]), + s([{NewKeyc3, 2}]), + ?line expect(23, [{NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(24, [{NewKeyc5, ?notInService}]), + s([{NewKeyc5, ?active}]), + ?line expect(25, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(26, [{NewKeyc5, ?destroy}]), + s([{NewKeyc3, 3}]), + ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]), + otp_1128(). + +%% Req. system group +simple_standard_test() -> + ?DBG("simple_standard_test -> entry",[]), + gn([[1,1]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3]]), + ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6]]), + ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1]]), + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2]]), + ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1]]), + ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1,1]]), + ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[sysDescr]]), + ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr,0]]), + ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr]]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{[sysDescr], noSuchObject}])), + g([[1,6,7,0]]), + ?line ?v1_2(expect(41, noSuchName, 1, any), + expect(3, [{[1,6,7,0], noSuchObject}])), + gn([[1,13]]), + ?line ?v1_2(expect(4, noSuchName,1, any), + expect(4, [{[1,13], endOfMibView}])), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + g([[sysLocation, 0]]), + ?line expect(6, [{[sysLocation, 0], "new_value"}]), + io:format("Testing noSuchName and badValue...~n"), + s([{[sysServices,0], 3}]), + ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any), + s([{[sysLocation, 0], i, 3}]), + ?line expect(62, ?v1_2(badValue, wrongType), 1, any), + ?DBG("simple_standard_test -> done",[]), + ok. + +%% This is run in the agent node +db_notify_client(suite) -> []; +db_notify_client(Config) when list(Config) -> + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p", + [SaNode,MgrNode,MibDir]), + snmpa_local_db:register_notify_client(self(),?MODULE), + + %% This call (the manager) will issue to set operations, so + %% we expect to receive to notify(insert) calls. + try_test(db_notify_client_test), + + ?DBG("await first notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok + end, + + ?DBG("await second notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok + end, + + snmpa_local_db:unregister_notify_client(self()). + + +%% This is run in the manager node +db_notify_client_test() -> + ?DBG("set first new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + + ?DBG("set second new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]). + +notify(Pid,What) -> + ?DBG("notify(~p,~p) -> called",[Pid,What]), + Pid ! {db_notify_test_reply,What}. + + +%% Req: system group, OLD-SNMPEA-MIB, Klas1 +big_test() -> + ?DBG("big_test -> testing simple next/get/set @ master agent...",[]), + simple_standard_test(), + + ?DBG("big_test -> testing simple next/get/set @ subagent...",[]), + gn([[klas1]]), + ?line expect(1, [{[fname,0], ""}]), + g([[fname,0]]), + ?line expect(2, [{[fname,0], ""}]), + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[fname,0]]), + ?line expect(4, [{[fname,0], "test set"}]), + + ?DBG("big_test -> " + "testing next from last instance in master to subagent...",[]), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname,0], "test set"}]), + s([{[fname,0], s, ""}]), + ?line expect(52, [{[fname,0], ""}]), + + table_test(), + + ?DBG("big_test -> adding one row in subagent table",[]), + _FTab = [friendsEntry], + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {[friendsEntry, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [friendsEntry, [3, 3]]]), + ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?active}]), + s([{[friendsEntry, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]), + + otp_1131(), + + ?DBG("big_test -> adding two rows in subagent table with special INDEX", + []), + s([{[kompissEntry, [1, 3]], s, "kompis3"}, + {[kompissEntry, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?createAndGo}]), + g([[kompissEntry, [1, 3]], + [kompissEntry, [2, 3]]]), + ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + gn([[kompissEntry, [1]], + [kompissEntry, [2]]]), + ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + s([{[kompissEntry, [1, 2]], s, "kompis3"}, + {[kompissEntry, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?createAndGo}]), + gn([[kompissEntry, [1, 1]], + [kompissEntry, [2, 1]]]), + ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?active}]), + s([{[kompissEntry, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]), + s([{[kompissEntry, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]), + ?DBG("big_test -> done",[]), + ok. + +%% Req. system group, Klas2, OLD-SNMPEA-MIB +big_test_2() -> + p("Testing simple next/get/set @ master agent (2)..."), + simple_standard_test(), + + p("Testing simple next/get/set @ subagent (2)..."), + gn([[klas2]]), + ?line expect(1, [{[fname2,0], ""}]), + g([[fname2,0]]), + ?line expect(2, [{[fname2,0], ""}]), + s([{[fname2,0], s, "test set"}]), + ?line expect(3, [{[fname2,0], "test set"}]), + g([[fname2,0]]), + ?line expect(4, [{[fname2,0], "test set"}]), + + otp_1298(), + + p("Testing next from last object in master to subagent (2)..."), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname2,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname2,0], "test set"}]), + + table_test(), + + p("Adding one row in subagent table (2)"), + _FTab = [friendsEntry2], + s([{[friendsEntry2, [2, 3]], s, "kompis3"}, + {[friendsEntry2, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?createAndGo}]), + g([[friendsEntry2, [2, 3]], + [friendsEntry2, [3, 3]]]), + ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?active}]), + s([{[friendsEntry2, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]), + + p("Adding two rows in subagent table with special INDEX (2)"), + s([{[kompissEntry2, [1, 3]], s, "kompis3"}, + {[kompissEntry2, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?createAndGo}]), + g([[kompissEntry2, [1, 3]], + [kompissEntry2, [2, 3]]]), + ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + gn([[kompissEntry2, [1]], + [kompissEntry2, [2]]]), + ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + s([{[kompissEntry2, [1, 2]], s, "kompis3"}, + {[kompissEntry2, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?createAndGo}]), + gn([[kompissEntry2, [1, 1]], + [kompissEntry2, [2, 1]]]), + ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?active}]), + s([{[kompissEntry2, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]), + s([{[kompissEntry2, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]), + ok. + +%% Req. Test1 +multi_threaded_test() -> + p("Testing multi threaded agent..."), + g([[multiStr,0]]), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(1, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "pelle"}]), + ?line expect(2, [{[sysLocation, 0], "pelle"}]), + Pid ! continue, + ?line expect(3, [{[multiStr,0], "ok"}]), + + s([{[multiStr, 0], s, "block"}]), + Pid2 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(4, [{[sysUpTime,0], any}]), + g([[multiStr,0]]), + Pid3 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(5, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "kalle"}]), + Pid3 ! continue, + ?line expect(6, [{[multiStr,0], "ok"}]), + Pid2 ! continue, + ?line expect(7, [{[multiStr,0], "block"}]), + ?line expect(8, [{[sysLocation,0], "kalle"}]). + +%% Req. Test1, TestTrapv2 +mt_trap_test(MA) -> + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + snmpa:send_trap(MA, mtTrap, "standard trap"), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(2, [{[sysUpTime,0], any}]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + Pid ! continue, + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [2]}, + {[multiStr,0], "ok"}]). + + +get_multi_pid() -> + get_multi_pid(10). +get_multi_pid(0) -> + ?line ?FAIL(no_global_name); +get_multi_pid(N) -> + sleep(1000), + case global:whereis_name(snmp_multi_tester) of + Pid when pid(Pid) -> Pid; + _ -> get_multi_pid(N-1) + end. + +%% Req. Test1 +types_v2_test() -> + p("Testing v2 types..."), + + s([{[bits1,0], 2#10}]), + ?line expect(1, [{[bits1,0], ?str(2#10)}]), + g([[bits1,0]]), + ?line expect(2, [{[bits1,0], ?str(2#101)}]), + + s([{[bits2,0], 2#11000000110}]), + ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]), + g([[bits2,0]]), + ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]), + + g([[bits3,0]]), + ?line expect(50, genErr, 1, any), + + g([[bits4,0]]), + ?line expect(51, genErr, 1, any), + + s([{[bits1,0], s, [2#10]}]), + ?line expect(6, ?v1_2(badValue, wrongValue), 1, any), + + s([{[bits2,0], 2#11001001101010011}]), + ?line expect(7, ?v1_2(badValue, wrongValue), 1, any). + + +%% Req. Test1 +implied_test(MA) -> + ?LOG("implied_test -> start",[]), + p("Testing IMPLIED..."), + + snmpa:verbosity(MA,trace), + snmpa:verbosity(MA,trace), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = "apa", + Idx2 = "qq", + ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]), + ?line expect(1, [{[testStatus, Idx1], ?createAndGo}, + {[testDescr, Idx1], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]), + ?line expect(2, [{[testStatus, Idx2], ?createAndGo}, + {[testDescr, Idx2], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr)",[]), + gn([[testDescr]]), + ?line expect(3, [{[testDescr,Idx1], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr) of row 1",[]), + gn([[testDescr,Idx1]]), + ?line expect(4, [{[testDescr,Idx2], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?destroy}]), + ?line expect(5, [{[testStatus, Idx1], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?destroy}]), + ?line expect(6, [{[testStatus, Idx2], ?destroy}]), + + %% Try the same in other table + Idx3 = [1, "apa"], + Idx4 = [1, "qq"], + ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]), + ?line expect(1, [{[testStatus2, Idx3], ?createAndGo}, + {[testDescr2, Idx3], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]), + ?line expect(2, [{[testStatus2, Idx4], ?createAndGo}, + {[testDescr2, Idx4], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr2)",[]), + gn([[testDescr2]]), + ?line expect(3, [{[testDescr2,Idx3], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr2) of row 1",[]), + gn([[testDescr2,Idx3]]), + ?line expect(4, [{[testDescr2,Idx4], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?destroy}]), + ?line expect(5, [{[testStatus2, Idx3], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?destroy}]), + ?line expect(6, [{[testStatus2, Idx4], ?destroy}]), + + snmpa:verbosity(MA,log), + + ?LOG("implied_test -> done",[]). + + + +%% Req. Test1 +sparse_table_test() -> + p("Testing sparse table..."), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + s([{[sparseStatus, Idx1], i, ?createAndGo}, + {[sparseDescr, Idx1], s, "row 1"}]), + ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo}, + {[sparseDescr, Idx1], "row 1"}]), + s([{[sparseStatus, Idx2], i, ?createAndGo}, + {[sparseDescr, Idx2], s, "row 2"}]), + ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo}, + {[sparseDescr, Idx2], "row 2"}]), + ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2], + [sparseStatus,Idx1], [sparseStatus,Idx2]]), + gb(0,5,[[sparseIndex]])), + ?line expect(3, [{[sparseDescr,Idx1], "row 1"}, + {[sparseDescr,Idx2], "row 2"}, + {[sparseStatus,Idx1], ?active}, + {[sparseStatus,Idx2], ?active}, + {[sparseStr,0], "slut"}]), + % Delete the rows + s([{[sparseStatus, Idx1], i, ?destroy}]), + ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]), + s([{[sparseStatus, Idx2], i, ?destroy}]), + ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]). + + +%% Req. Test1 +cnt_64_test(MA) -> + ?LOG("start cnt64 test (~p)",[MA]), + snmpa:verbosity(MA,trace), + ?LOG("start cnt64 test",[]), + p("Testing Counter64, and at the same time, RowStatus is not last column"), + + ?DBG("get cnt64",[]), + g([[cnt64,0]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(1, noSuchName, 1, any), + expect(1, [{[cnt64,0],18446744073709551615}])), + ?DBG("get-next cnt64",[]), + gn([[cnt64]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]), + expect(2, [{[cnt64,0],18446744073709551615}])), + ?DBG("send cntTrap",[]), + snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"}, + {cnt64, 10}, + {sysLocation, "here"}]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"}, + {[sysLocation,0], "here"}]), + expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [1]}, + {[sysContact,0], "pelle"}, + {[cnt64,0], 10}, + {[sysLocation,0], "here"}])), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + ?DBG("create row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]), + ?DBG("create row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]), + + ?DBG("get-next (cntIndex)",[]), + gn([[cntIndex]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]), + expect(3, [{[cntCnt,Idx1], 0}])), + % Delete the rows + ?DBG("delete row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(4, [{[cntStatus, Idx1], ?destroy}]), + ?DBG("delete row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(5, [{[cntStatus, Idx2], ?destroy}]), + catch snmpa:verbosity(MA,log), + ?DBG("done",[]), + ok. + +%% Req. Test1 +opaque_test() -> + p("Testing Opaque datatype..."), + g([[opaqueObj,0]]), + ?line expect(1, [{[opaqueObj,0], "opaque-data"}]). + +%% Req. OLD-SNMPEA-MIB +api_test(MaNode) -> + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [intAgentIpAddress]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, + oid_to_name, [OID]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [[1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, + int_to_enum, ['RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]), + ?line case snmp:date_and_time() of + List when list(List), length(List) == 8 -> ok; + List when list(List), length(List) == 11 -> ok + end. + +%% Req. Klas3 +api_test2() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]), + g([[fname4,0]]), + ?line expect(2, [{[fname4,0], 1}]). + +api_test3() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]). + + +unreg_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[snmpInPkts, 0], any}]). + +load_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[fname,0], ""}]). + +%% Req. Klas1 +load_test_sa() -> + gn([[?v1_2(sysServices,sysORLastChange), 0]]), + ?line expect(1, [{[fname,0], any}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_get() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0], Key1c4, [fname,0],Key1c3, + [sysName,0]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,0], "test"}]), + g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]), + ?line ?v1_2(expect(2, noSuchName, [1,4], any), + expect(2, [{[1,3,7,1], noSuchObject}, + {Key1c4, 2}, + {[sysDescr,0], "Erlang SNMP agent"}, + {[1,3,7,2], noSuchObject}, + {Key1c3, 2}, + {[sysDescr,0], "Erlang SNMP agent"}])). + +%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3. +do_mul_get_err() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]), + ?line ?v1_2(expect(1, noSuchName, 5, any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,2], noSuchInstance}])), + g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname3,0], noSuchObject}, + {Key1c3, 2}, + {[sysName,1], noSuchInstance}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, {[fname,0], "test set"}, + {Key1c3, 2}, {[sysName,0], "test"}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next_err() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[1,3,6,999], endOfMibView}, + {[fname,0], "test set"}, + {[1,3,90], endOfMibView}, + {Key1c3, 2}, + {[sysName,0], "test"}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set() -> + p("Adding one row in subagent table, and one in master table"), + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [sysLocation,0], + [friendsEntry, [3, 3]]]), + ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"}, + {[sysLocation,0], "new_value"}, + {[friendsEntry, [3, 3]], ?active}]), + g([NewKeyc4]), + ?line expect(3, [{NewKeyc4, 2}]), + s([{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]), + ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + p("Adding one row in subagent table, and one in master table"), + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {NewKeyc3, 2}, + {[sysUpTime,0], 45}, % sysUpTime (readOnly) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any), + g([[friendsEntry, [2, 3]]]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])), + g([NewKeyc4]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB +sa_mib() -> + g([[sa, [2,0]]]), + ?line expect(1, [{[sa, [2,0]], 3}]), + s([{[sa, [1,0]], s, "sa_test"}]), + ?line expect(2, [{[sa, [1,0]], "sa_test"}]). + +ma_trap1(MA) -> + snmpa:send_trap(MA, testTrap2, "standard trap"), + ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]), + snmpa:send_trap(MA, testTrap1, "standard trap"), + ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]). + +ma_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap2(MA) -> + snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1}, + {ifAdminStatus, [1], 1}, + {ifOperStatus, [1], 2}]), + ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}]). + +sa_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]], + "pelle"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}]). + +ma_v2_trap1(MA) -> + ?DBG("ma_v2_traps -> entry with MA = ~p => " + "send standard trap: testTrapv22",[MA]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]), + snmpa:send_trap(MA, testTrapv21, "standard trap"), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmp ++ [1]}]). + +ma_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}]). + +%% Note: This test case takes a while... actually a couple of minutes. +ma_v2_inform1(MA) -> + ?DBG("ma_v2_inform -> entry with MA = ~p => " + "send notification: testTrapv22",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag1, self()}, + "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag1, [_]} -> + ok; + {snmp_targets, tag1, Addrs1} -> + ?line ?FAIL({bad_addrs, Addrs1}) + after + 5000 -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag1, {got_response, _}} -> + ok; + {snmp_notification, tag1, {no_response, _}} -> + ?line ?FAIL(no_response) + after + 20000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + + %% + %% -- The rest is possibly erroneous... + %% + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag2, self()}, + "standard inform", []), + ?line expect(2, {inform, false}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag2, [_]} -> + ok; + {snmp_targets, tag2, Addrs2} -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]), + ?line ?FAIL({bad_addrs, Addrs2}) + after + 5000 -> + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag2, {got_response, _}} -> + ?line ?FAIL(got_response); + {snmp_notification, tag2, {no_response, _}} -> + ok + after + 240000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag2) timeout",[]), + ?line ?FAIL(nothing_at_all) + end. + + +ma_v1_2_v2_trap(MA) -> + snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmpTraps ++ [3]}, + {[ifIndex, 1], 1}, + {[snmpTrapEnterprise, 0], [1,2,3]}]). + + +ma_v1_2_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}, + {[snmpTrapEnterprise, 0], ?system}]). + + +sa_v1_2_v2_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + +sa_v1_2_v2_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], "pelle"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +sa_v1_2_v2_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 2]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_bad_value() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2}, + {[sa, [2,0]], 5}, % badValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, badValue, 2, any), + s([{NewKeyc3, 2}, + {[sa, [2,0]], 6}, % wrongValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, ?v1_2(badValue, wrongValue), 2, any), + g([NewKeyc4]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_gen_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2},{NewKeyc4, 2}, + {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]), + ?line expect(1, genErr, 4, any), +% The row might have been added; we don't know. +% (as a matter of fact we do - it is added, because the agent +% first sets its own vars, and then th SAs. Lets destroy it. + s([{NewKeyc5, ?destroy}]), + ?line expect(2, [{NewKeyc5, ?destroy}]). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_too_big() -> + g([[sa, [4,0]]]), + ?line expect(1, tooBig). + +%% Req. Klas1, system group, snmp group (v1/v2) +next_across_sa() -> + gn([[sysDescr],[klas1,5]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {[snmpInPkts, 0], any}]). + +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2} +%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2} +%% Req. Klas3, Klas4 +undo_test() -> + s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]), + ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any), + s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]), + ?line expect(3, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]), + ?line expect(4, ?v1_2(genErr, commitFailed), 1, any), +% unfortunatly we don't know if we'll get undoFailed or commitFailed. +% it depends on which order the agent traverses the varbind list. +% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]), +% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]), + ?line expect(6, genErr, 2, any). + +%% Req. Klas3, Klas4 +bad_return() -> + g([[fStatus4,4], + [fName4,4]]), + ?line expect(4, genErr, 2, any), + g([[fStatus4,5], + [fName4,5]]), + ?line expect(5, genErr, 1, any), + g([[fStatus4,6], + [fName4,6]]), + ?line expect(6, genErr, 2, any), + gn([[fStatus4,7], + [fName4,7]]), + ?line expect(7, genErr, 2, any), + gn([[fStatus4,8], + [fName4,8]]), + ?line expect(8, genErr, 1, any), + gn([[fStatus4,9], + [fName4,9]]), + ?line expect(9, genErr, 2, any). + + +%%%----------------------------------------------------------------- +%%% Test the implementation of standard mibs. +%%% We should *at least* try to GET all variables, just to make +%%% sure the instrumentation functions work. +%%% Note that many of the functions in the standard mib is +%%% already tested by the normal tests. +%%%----------------------------------------------------------------- +standard_mibs(suite) -> + [snmp_standard_mib, snmp_community_mib, + snmp_framework_mib, + snmp_target_mib, snmp_notification_mib, + snmp_view_based_acm_mib]. + +standard_mibs_2(suite) -> + [snmpv2_mib_2, snmp_community_mib_2, + snmp_framework_mib_2, + snmp_target_mib_2, snmp_notification_mib_2, + snmp_view_based_acm_mib_2]. + +standard_mibs_3(suite) -> + [snmpv2_mib_3,snmp_framework_mib_3, snmp_mpd_mib_3, + snmp_target_mib_3, snmp_notification_mib_3, + snmp_view_based_acm_mib_3, snmp_user_based_sm_mib_3]. + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v1. +%% o Test the counters and control objects in SNMP-STANDARD-MIB +%%----------------------------------------------------------------- +snmp_standard_mib(suite) -> []; +snmp_standard_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?DBG("snmp_standard_mib -> std_mib_init", []), + try_test(std_mib_init), + + ?DBG("snmp_standard_mib -> std_mib_a", []), + InBadVsns = try_test(std_mib_a), + put(vsn, v2), + ?DBG("snmp_standard_mib -> std_mib_read", []), + try_test(std_mib_read), + put(vsn, v1), + + ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]), + Bad = try_test(std_mib_b, [InBadVsns]), + ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []), + try_test(std_mib_read, [], [{community, "bad community"}]), + ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []), + try_test(std_mib_write, [], [{community, "public"}]), + ?DBG("snmp_standard_mib -> std_mib_asn_err", []), + try_test(std_mib_asn_err), + ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]), + try_test(std_mib_c, [Bad]), + ?DBG("snmp_standard_mib -> std_mib_a", []), + try_test(standard_mib_a), + + ?DBG("snmp_standard_mib -> std_mib_finish", []), + try_test(std_mib_finish), + ?DBG("snmp_standard_mib -> std_mib_test_finish", []), + try_test(standard_mib_test_finish, [], [{community, "bad community"}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_a() -> + ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]), + ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]), + ?line OutPkts2 = OutPkts + 1, + %% There are some more counters we could test here, but it's not that + %% important, since they are removed from SNMPv2-MIB. + ok. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_init() -> + %% disable authentication failure traps. (otherwise w'd get many of + %% them - this is also a test to see that it works). + s([{[snmpEnableAuthenTraps,0], 2}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_finish() -> + %% enable again + s([{[snmpEnableAuthenTraps,0], 1}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_test_finish() -> + %% force a authenticationFailure + std_mib_write(), + %% check that we got a trap + ?line expect(2, trap, [1,2,3], 4, 0, []). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_read() -> + ?DBG("std_mib_read -> entry", []), + g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply + ?DBG("std_mib_read -> await timeout (i.e. no reply)", []), + ?line expect(1, timeout). % make sure we don't get a trap! + + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_write() -> + ?DBG("std_mib_write -> entry", []), + s([{[sysLocation, 0], "new_value"}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_asn_err() -> + snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]). + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v2 and v3. +%% o Test the counters and control objects in SNMPv2-MIB +%%----------------------------------------------------------------- +snmpv2_mib_2(suite) -> []; +snmpv2_mib_2(Config) when list(Config) -> + ?LOG("snmpv2_mib_2 -> start",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?DBG("snmpv2_mib_2 -> standard mib init",[]), + try_test(std_mib_init), + + ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]), + InBadVsns = try_test(std_mib_a), + + ?DBG("snmpv2_mib_2 -> make a bad version read",[]), + put(vsn, v1), + try_test(std_mib_read), + + ?DBG("snmpv2_mib_2 -> bad version read",[]), + put(vsn, v2), + Bad = try_test(std_mib_b, [InBadVsns]), + + ?DBG("snmpv2_mib_2 -> read with bad community",[]), + try_test(std_mib_read, [], [{community, "bad community"}]), + + ?DBG("snmpv2_mib_2 -> write with public community",[]), + try_test(std_mib_write, [], [{community, "public"}]), + + ?DBG("snmpv2_mib_2 -> asn err",[]), + try_test(std_mib_asn_err), + + ?DBG("snmpv2_mib_2 -> check counters",[]), + try_test(std_mib_c, [Bad]), + + ?DBG("snmpv2_mib_2 -> get som counters",[]), + try_test(snmpv2_mib_a), + + ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]), + try_test(std_mib_finish), + + ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, " + "then disable auth traps",[]), + try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]), + + ?LOG("snmpv2_mib_2 -> done",[]). + +%% Req. SNMPv2-MIB +snmpv2_mib_3(suite) -> []; +snmpv2_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + InBadVsns = try_test(std_mib_a), + put(vsn, v1), + try_test(std_mib_read), + put(vsn, v3), + _Bad = try_test(std_mib_b, [InBadVsns]), + try_test(snmpv2_mib_a), + + try_test(std_mib_finish). + +-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]). + +%% Req. SNMPv2-MIB +snmpv2_mib_test_finish() -> + %% force a authenticationFailure + ?DBG("ma_v2_inform -> write to std mib",[]), + std_mib_write(), + + %% check that we got a trap + ?DBG("ma_v2_inform -> await trap",[]), + ?line expect(2, v2trap, [{[sysUpTime,0], any}, + {[snmpTrapOID,0], ?authenticationFailure}]), + + %% and the the inform + ?DBG("ma_v2_inform -> await inform",[]), + ?line expect(2, {inform,true}, [{[sysUpTime,0], any}, + {[snmpTrapOID,0],?authenticationFailure}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_a() -> + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + + ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]), + InBadVsns. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_b(InBadVsns) -> + ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]), + ?line InBadVsns2 = InBadVsns + 1, + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] = + get_req(4, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + {InBadCommunityNames, InBadCommunityUses, InASNErrs}. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) -> + ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] = + get_req(1, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + ?line InBadCommunityNames2 = InBadCommunityNames + 1, + ?line InBadCommunityUses2 = InBadCommunityUses + 1, + ?line InASNErrs2 = InASNErrs + 1. + +%% Req. SNMPv2-MIB +snmpv2_mib_a() -> + ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]), + s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]), + ?line expect(3, [{[snmpSetSerialNo,0], SetSerial}, + {[sysLocation, 0], "val2"}]), + s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]), + ?line expect(4, inconsistentValue, 2, + [{[sysLocation, 0], "val3"}, + {[snmpSetSerialNo,0], SetSerial}]), + ?line ["val2"] = get_req(5, [[sysLocation,0]]). + + +%%----------------------------------------------------------------- +%% o Bad community uses/name is tested already +%% in SNMPv2-MIB and STANDARD-MIB. +%% o Test add/deletion of rows. +%%----------------------------------------------------------------- +snmp_community_mib(suite) -> []; +snmp_community_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + try_test(snmp_community_mib), + ?line unload_master("SNMP-COMMUNITY-MIB"). + +snmp_community_mib_2(X) -> snmp_community_mib(X). + +%% Req. SNMP-COMMUNITY-MIB +snmp_community_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o Test engine boots / time +%%----------------------------------------------------------------- +snmp_framework_mib(suite) -> []; +snmp_framework_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + try_test(snmp_framework_mib), + ?line unload_master("SNMP-FRAMEWORK-MIB"). + +snmp_framework_mib_2(X) -> snmp_framework_mib(X). + +snmp_framework_mib_3(suite) -> []; +snmp_framework_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(snmp_framework_mib). + + +%% Req. SNMP-FRAMEWORK-MIB +snmp_framework_mib() -> + ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]), + ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]), + sleep(5000), + ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]), + if + EngineTime+7 < EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + EngineTime+4 > EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + true -> ok + end, + ?line case get_req(4, [[snmpEngineBoots,0]]) of + [Boots] when integer(Boots) -> ok; + Else -> ?FAIL(Else) + end, + ok. + +%%----------------------------------------------------------------- +%% o Test the counters +%%----------------------------------------------------------------- +snmp_mpd_mib_3(suite) -> []; +snmp_mpd_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + UnknownPDUHs = try_test(snmp_mpd_mib_a), + try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]), + try_test(snmp_mpd_mib_c, [UnknownPDUHs]). + + +%% Req. SNMP-MPD-MIB +snmp_mpd_mib_a() -> + ?line [UnknownSecs, InvalidMsgs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0]]), + Pdu = #pdu{type = 'get-request', + request_id = 23, + error_status = noError, + error_index = 0, + varbinds = []}, + SPdu = #scopedPdu{contextEngineID = "agentEngine", + contextName = "", + data = Pdu}, + ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu), + V3Hdr1 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [7], + msgSecurityModel = 23, % bad sec model + msgSecurityParameters = []}, + V3Hdr2 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [6], % bad flag combination + msgSecurityModel = 3, + msgSecurityParameters = []}, + Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1, + data = SPDUBytes}, + Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2, + data = SPDUBytes}, + ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1), + ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2), + snmp_test_mgr:send_bytes(MsgBytes1), + snmp_test_mgr:send_bytes(MsgBytes2), + + ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0], + [snmpUnknownPDUHandlers, 0]]), + ?line UnknownSecs2 = UnknownSecs + 1, + ?line InvalidMsgs2 = InvalidMsgs + 1, + UnknownPDUHs. + +-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]). +snmp_mpd_mib_b() -> + g([[sysUpTime,0]]), + ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]). + + +snmp_mpd_mib_c(UnknownPDUHs) -> + ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]), + ?line UnknownPDUHs2 = UnknownPDUHs + 1. + + +snmp_target_mib(suite) -> []; +snmp_target_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-TARGET-MIB"), + try_test(snmp_target_mib), + ?line unload_master("SNMP-TARGET-MIB"). + +snmp_target_mib_2(X) -> snmp_target_mib(X). + +snmp_target_mib_3(X) -> snmp_target_mib(X). + +snmp_target_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +snmp_notification_mib(suite) -> []; +snmp_notification_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + try_test(snmp_notification_mib), + ?line unload_master("SNMP-NOTIFICATION-MIB"). + +snmp_notification_mib_2(X) -> snmp_notification_mib(X). + +snmp_notification_mib_3(X) -> snmp_notification_mib(X). + +snmp_notification_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o add/delete views and try them +%% o try boundaries +%%----------------------------------------------------------------- +snmp_view_based_acm_mib(suite) -> []; +snmp_view_based_acm_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master("Test2"), + snmp_view_based_acm_mib(), + ?line unload_master("Test2"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib() -> + snmpa:verbosity(net_if,trace), + snmpa:verbosity(master_agent,trace), + ?LOG("start snmp_view_based_acm_mib test",[]), + %% The user "no-rights" is present in USM, and is mapped to security + %% name 'no-rights", which is not present in VACM. + %% So, we'll add rights for it, try them and delete them. + %% We'll give "no-rights" write access to tDescr.0 and read access + %% to tDescr2.0 + %% These are the options we'll use to the mgr + Opts = [{user, "no-rights"}, {community, "no-rights"}], + %% Find the valid secmodel, and one invalid secmodel. + {SecMod, InvSecMod} = + case get(vsn) of + v1 -> {?SEC_V1, ?SEC_V2C}; + v2 -> {?SEC_V2C, ?SEC_USM}; + v3 -> {?SEC_USM, ?SEC_V1} + end, + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Now, add a mapping from "no-rights" -> "no-rights-group" + GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]], + GRow1 = + [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"}, + {GRow1Status, ?createAndGo}], + ?DBG("set '~p'",[GRow1]), + ?line try_test(do_set, [GRow1]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Create a mapping for another sec model, and make sure it dosn't + %% give us access + GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]], + GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"}, + {GRow2Status, ?createAndGo}], + + ?DBG("set '~p'",[GRow2]), + ?line try_test(do_set, [GRow2]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [GRow2Status]), + + RVName = "rv_name", + WVName = "wv_name", + + %% Access row + ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1], + ARow1Status = [vacmAccessStatus, ARow1Idx], + ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1}, + {[vacmAccessReadViewName, ARow1Idx], RVName}, + {[vacmAccessWriteViewName, ARow1Idx], WVName}, + {ARow1Status, ?createAndGo}], + + %% This access row would give acces, if InvSecMod was valid. + ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1], + ARow2Status = [vacmAccessStatus, ARow2Idx], + ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1}, + {[vacmAccessReadViewName, ARow2Idx], "internet"}, + {[vacmAccessWriteViewName, ARow2Idx], "internet"}, + {ARow2Status, ?createAndGo}], + + ?line try_test(do_set, [ARow2]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [ARow2Status]), + + + %% Add valid row + ?line try_test(do_set, [ARow1]), + + ?line try_test(use_no_rights, [], Opts), + + %% Create the view family + VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access + VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access + VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access + VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access + VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx], + VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx], + VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx], + VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx], + + ?line try_test(add_row, [VRow1Status]), + ?line try_test(add_row, [VRow2Status]), + ?line try_test(add_row, [VRow3Status]), + + %% We're supposed to have access now... + ?line try_test(use_rights, [], Opts), + + %% Change Row3 to Row4 + ?line try_test(del_row, [VRow3Status]), + ?line try_test(add_row, [VRow4Status]), + + %% We should still have access... + ?line try_test(use_rights, [], Opts), + + %% Delete rows + ?line try_test(del_row, [GRow1Status]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete rest of rows + ?line try_test(del_row, [ARow1Status]), + ?line try_test(del_row, [VRow1Status]), + ?line try_test(del_row, [VRow2Status]), + ?line try_test(del_row, [VRow4Status]), + + ?line try_test(use_no_rights, [], Opts), + snmpa:verbosity(master_agent,log). + +do_set(Row) -> + s(Row), + expect(1, Row). + +add_row(RowStatus) -> + s([{RowStatus, ?createAndGo}]), + expect(1, [{RowStatus, ?createAndGo}]). + +del_row(RowStatus) -> + s([{RowStatus, ?destroy}]), + expect(1, [{RowStatus, ?destroy}]). + + + +use_no_rights() -> + g([[xDescr,0]]), + ?v1_2_3(expect(11, noSuchName, 1, any), + expect(12, [{[xDescr,0], noSuchObject}]), + expect(13, authorizationError, 1, any)), + g([[xDescr2,0]]), + ?v1_2_3(expect(21, noSuchName, 1, any), + expect(22, [{[xDescr2,0], noSuchObject}]), + expect(23, authorizationError, 1, any)), + gn([[xDescr]]), + ?v1_2_3(expect(31, noSuchName, 1, any), + expect(32, [{[xDescr], endOfMibView}]), + expect(33, authorizationError, 1, any)), + s([{[xDescr,0], "tryit"}]), + ?v1_2_3(expect(41, noSuchName, 1, any), + expect(42, noAccess, 1, any), + expect(43, authorizationError, 1, any)). + + +use_rights() -> + g([[xDescr,0]]), + expect(1, [{[xDescr,0], any}]), + g([[xDescr2,0]]), + expect(2, [{[xDescr2,0], any}]), + s([{[xDescr,0], "tryit"}]), + expect(3, noError, 0, any), + g([[xDescr,0]]), + expect(4, [{[xDescr,0], "tryit"}]). + +mk_ln(X) -> + [length(X) | X]. + +%%----------------------------------------------------------------- +%% o add/delete users and try them +%% o test all secLevels +%% o test all combinations of protocols +%% o try bad ops; check counters +%%----------------------------------------------------------------- +snmp_user_based_sm_mib_3(suite) -> []; +snmp_user_based_sm_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + _AgentDir = ?config(agent_dir, Config), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + + %% The newUser used here already has VACM access. + + %% Add a new user in the simplest way; just createAndGo + try_test(v3_sync, [[{usm_add_user1, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new user + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"), + DesKey1 = lists:sublist(ShaKey1, 16), + + %% Change the new user's keys - 1 + try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + MgrDir = ?config(mgr_dir, Config), + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"), + DesKey2 = lists:sublist(ShaKey2, 16), + + %% Change the new user's keys - 2 + ?line try_test(v3_sync, + [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + reset_usm_mgr(MgrDir), + ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2), + ?line load_master("Test2"), + ?line try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Change the new user's keys - 3 + ?line try_test(v3_sync, + [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new keys + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Try some read requests + ?line try_test(v3_sync, [[{usm_read, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Delete the new user + ?line try_test(v3_sync, [[{usm_del_user, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try some bad requests + ?line try_test(v3_sync, [[{usm_bad, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("SNMP-USER-BASED-SM-MIB"). + +-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]). + +usm_add_user1() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +usm_use_user() -> + v2_proc(). + + +%% Change own public keys +usm_key_change1(ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_shaxxxxxxxxxx", + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_desxxxxxx", + DesKey), + Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change own private keys +usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change other's public keys +usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}], + s(Vbs1), + ?line expect(1, noAccess, 1, any), + Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs2), + ?line expect(2, noAccess, 1, any), + + + Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs3), + ?line expect(1, Vbs3). + +usm_read() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ?line g([[usmUserSecurityName, NewRowIndex], + [usmUserCloneFrom, NewRowIndex], + [usmUserAuthKeyChange, NewRowIndex], + [usmUserOwnAuthKeyChange, NewRowIndex], + [usmUserPrivKeyChange, NewRowIndex], + [usmUserOwnPrivKeyChange, NewRowIndex]]), + ?line expect(1, + [{[usmUserSecurityName, NewRowIndex], "newUser"}, + {[usmUserCloneFrom, NewRowIndex], [0,0]}, + {[usmUserAuthKeyChange, NewRowIndex], ""}, + {[usmUserOwnAuthKeyChange, NewRowIndex], ""}, + {[usmUserPrivKeyChange, NewRowIndex], ""}, + {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]), + ok. + + + +usm_del_user() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]). + +-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]). + +-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]). + +-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]). + +-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]). + +-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]). + +usm_bad() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, inconsistentName, 1, any), + + RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs2), + ?line expect(2, wrongValue, 1, any), + + RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs3), + ?line expect(3, Vbs3), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]), + ?line expect(4, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]), + ?line expect(5, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]), + ?line expect(6, wrongValue, 1, any), + ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]), + ?line expect(7, wrongValue, 1, any), + + Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs4), + ?line expect(1, Vbs4), + + ok. + + +%%----------------------------------------------------------------- +%% Loop through entire MIB, to make sure that all instrum. funcs +%% works. +%% Load all std mibs that are not loaded by default. +%%----------------------------------------------------------------- +loop_mib(suite) -> []; +loop_mib(Config) when list(Config) -> + ?LOG("loop_mib -> initiate case",[]), + %% snmpa:verbosity(master_agent,debug), + %% snmpa:verbosity(mib_server,info), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]), + ?line load_master_std("SNMP-MPD-MIB"), + ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?DBG("loop_mib -> try",[]), + try_test(loop_mib_1), + ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]), + ?line unload_master("SNMP-MPD-MIB"), + ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + %% snmpa:verbosity(master_agent,log), + %% snmpa:verbosity(mib_server,silence), + ?LOG("loop_mib -> done",[]). + + +loop_mib_2(suite) -> []; +loop_mib_2(Config) when list(Config) -> + ?LOG("loop_mib_2 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_2 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_2 -> load mibs",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_2 -> unload mibs",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?LOG("loop_mib_2 -> done",[]). + + +loop_mib_3(suite) -> []; +loop_mib_3(Config) when list(Config) -> + ?LOG("loop_mib_3 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_3 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_3 -> load mibs",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_3 -> unload mibs",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?LOG("loop_mib_3 -> done",[]). + + +%% Req. As many mibs all possible +loop_mib_1() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_1([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_1(Oid, N) -> + ?DBG("loop_it_1 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_1 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_1 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_1(NOid, N+1); + #pdu{type='get-response', error_status=noSuchName, error_index=1, + varbinds=[_]} -> + ?DBG("loop_it_1 -> done",[]), + N; + + #pdu{type = Type, error_status = Err, error_index = Idx, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs}) + end. + +%% Req. As many mibs all possible +loop_mib_2() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_2([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_2(Oid, N) -> + ?DBG("loop_it_2 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid, value = endOfMibView}]} -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p",[NOid]), + N; + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_2 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_2(NOid, N+1) + end. + + +%%%----------------------------------------------------------------- +%%% Testing of reported bugs and other tickets. +%%%----------------------------------------------------------------- + +reported_bugs(suite) -> + [otp_1128, otp_1129, otp_1131, otp_1162, + otp_1222, otp_1298, otp_1331, otp_1338, + otp_1342, otp_2776, otp_2979, otp_3187, otp_3725]. + +reported_bugs_2(suite) -> + [otp_1128_2, otp_1129_2, otp_1131_2, otp_1162_2, + otp_1222_2, otp_1298_2, otp_1331_2, otp_1338_2, + otp_1342_2, otp_2776_2, otp_2979_2, otp_3187_2]. + +reported_bugs_3(suite) -> + [otp_1128_3, otp_1129_3, otp_1131_3, otp_1162_3, + otp_1222_3, otp_1298_3, otp_1331_3, otp_1338_3, + otp_1342_3, otp_2776_3, otp_2979_3, otp_3187_3, + otp_3542]. + + +%% These are (ticket) test cases where the initiation has to be done +%% individually. +tickets(suite) -> + [otp_4394]. + +%%----------------------------------------------------------------- +%% Ticket: OTP-1128 +%% Slogan: Bug in handling of createAndWait set-requests. +%%----------------------------------------------------------------- +otp_1128(suite) -> []; +otp_1128(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1128), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1128_2(X) -> otp_1128(X). + +otp_1128_3(X) -> otp_1128(X). + +otp_1128() -> + io:format("Testing bug reported in ticket OTP-1128...~n"), + + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + + s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(29, [{NewKeyc5, ?notReady}]), + s([{NewKeyc5, ?active}, {NewKeyc3, 2}]), + ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(31, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(32, [{NewKeyc5, ?destroy}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1129, OTP-1169 +%% Slogan: snmpa:int_to_enum crashes on bad oids +%%----------------------------------------------------------------- +otp_1129(suite) -> []; +otp_1129(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + try_test(otp_1129_i, [node()]), + ?line unload_master("Klas3"). + +otp_1129_2(X) -> otp_1129(X). + +otp_1129_3(X) -> otp_1129(X). + +otp_1129_i(MaNode) -> + io:format("Testing bug reported in ticket OTP-1129...~n"), + false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]), + false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1131 +%% Slogan: Agent crashes / erlang node halts if RowIndex in a +%% setrequest is of bad type, e.g. an INDEX {INTEGER}, +%% and RowIdenx [3,2]. +%%----------------------------------------------------------------- +otp_1131(suite) -> []; +otp_1131(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas1"), + try_test(otp_1131), + ?line unload_master("Klas1"). + +otp_1131_2(X) -> otp_1131(X). + +otp_1131_3(X) -> otp_1131(X). + +otp_1131() -> + io:format("Testing bug reported in ticket OTP-1131...~n"), + s([{[friendsEntry, [2, 3, 1]], s, "kompis3"}, + {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1162 +%% Slogan: snmp_agent can't handle wrongValue from instrum.func +%%----------------------------------------------------------------- +otp_1162(suite) -> []; +otp_1162(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + try_test(otp_1162), + stop_subagent(SA). + +otp_1162_2(X) -> otp_1162(X). + +otp_1162_3(X) -> otp_1162(X). + +otp_1162() -> + s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok) + ?line expect(1, ?v1_2(badValue, wrongValue), 1, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1222 +%% Slogan: snmp agent crash if faulty index is returned from instrum +%%----------------------------------------------------------------- +otp_1222(suite) -> []; +otp_1222(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + ?line load_master("Klas4"), + try_test(otp_1222), + ?line unload_master("Klas3"), + ?line unload_master("Klas4"). + +otp_1222_2(X) -> otp_1222(X). + +otp_1222_3(X) -> otp_1222(X). + +otp_1222() -> + io:format("Testing bug reported in ticket OTP-1222...~n"), + s([{[fStatus4,1], 4}, {[fName4,1], 1}]), + ?line expect(1, genErr, 0, any), + s([{[fStatus4,2], 4}, {[fName4,2], 1}]), + ?line expect(2, genErr, 0, any). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1298 +%% Slogan: Negative INTEGER values are treated as positive. +%%----------------------------------------------------------------- +otp_1298(suite) -> []; +otp_1298(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1298), + ?line unload_master("Klas2"). + +otp_1298_2(X) -> otp_1298(X). + +otp_1298_3(X) -> otp_1298(X). + +otp_1298() -> + io:format("Testing bug reported in ticket OTP-1298...~n"), + s([{[fint,0], -1}]), + ?line expect(1298, [{[fint,0], -1}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1331 +%% Slogan: snmp_generic should return noError when deleting non-ex row +%%----------------------------------------------------------------- +otp_1331(suite) -> []; +otp_1331(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1331), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1331_2(X) -> otp_1331(X). + +otp_1331_3(X) -> otp_1331(X). + +otp_1331() -> + NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")], + s([{NewKeyc5, ?destroy}]), + ?line expect(1, [{NewKeyc5, ?destroy}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1338 +%% Slogan: snmp bug in initialisation of default values for mnesia tabs +%%----------------------------------------------------------------- +otp_1338(suite) -> []; +otp_1338(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1338), + ?line unload_master("Klas2"). + +otp_1338_2(X) -> otp_1338(X). + +otp_1338_3(X) -> otp_1338(X). + +otp_1338() -> + s([{[kStatus2, 7], i, ?createAndGo}]), + ?line expect(1, [{[kStatus2, 7], ?createAndGo}]), + g([[kName2, 7]]), + ?line expect(2, [{[kName2, 7], "JJJ"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1342 +%% Slogan: default impl of snmp table can't handle bad index access, +%% Set when INDEX is read-write gets into an infinite loop! +%%----------------------------------------------------------------- +otp_1342(suite) -> []; +otp_1342(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas4"), + try_test(otp_1342), + ?line unload_master("Klas4"). + +otp_1342_2(X) -> otp_1342(X). + +otp_1342_3(X) -> otp_1342(X). + +otp_1342() -> + s([{[fIndex5, 1], i, 1}, + {[fName5, 1], i, 3}, + {[fStatus5, 1], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1366 +%% Slogan: snmp traps not sent to all managers +%% Note: NYI! We need a way to tell the test server that we need +%% mgrs on two different machines. +%%----------------------------------------------------------------- +otp_1366(suite) -> []; +otp_1366(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1366), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1366_2(X) -> otp_1366(X). + +otp_1366_3(X) -> otp_1366(X). + +otp_1366() -> + ?INF("NOT YET IMPLEMENTED", []), + 'NYI'. + +%%----------------------------------------------------------------- +%% Ticket: OTP-2776 +%% Slogan: snmp:validate_date_and_time() fails when time is 00:00 +%%----------------------------------------------------------------- +otp_2776(suite) -> []; +otp_2776(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_2776). + +otp_2776_2(X) -> otp_2776(X). + +otp_2776_3(X) -> otp_2776(X). + +otp_2776() -> + io:format("Testing bug reported in ticket OTP-2776...~n"), + + Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0], + Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00 + Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0], + Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0], + Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0], + Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0], + Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2 + Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0], + Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4 + Dt10_invalid = [], + Dt11_invalid = [kalle,hobbe], + L = [{ 1, true, Dt01_valid}, + { 2, true, Dt02_valid}, + { 3, true, Dt03_valid}, + { 4, false, Dt04_invalid}, + { 5, true, Dt05_valid}, + { 6, true, Dt06_valid}, + { 7, false, Dt07_invalid}, + { 8, true, Dt08_valid}, + { 9, false, Dt09_invalid}, + {10, false, Dt10_invalid}, + {11, false, Dt11_invalid}], + + ?line ok = validate_dat(L). + + +validate_dat(L) -> validate_dat(L,[]). + +validate_dat([],V) -> + Fun = fun({_,X}) -> case X of + ok -> false; + _ -> true + end + end, + validate_dat1( lists:reverse( lists:filter(Fun,V) ) ); +validate_dat([{Id,E,Dat}|T],V) -> + validate_dat(T,[validate_dat2(Id,E,Dat) | V]). + +validate_dat1([]) -> ok; +validate_dat1(L) -> {error,L}. + +validate_dat2(Id, E, Dat) -> + Res = case {E,snmp:validate_date_and_time(Dat)} of + {E,E} -> ok; + {E,A} -> {E,A} + end, + {Id, Res}. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-2979 +%% Slogan: get-next on more than 1 column in an empty table +%% returns bad response. +%%----------------------------------------------------------------- +otp_2979(suite) -> []; +otp_2979(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Test1"), + ?line init_old(), + try_test(otp_2979), + ?line unload_master("Test1"). + +otp_2979_2(X) -> otp_2979(X). + +otp_2979_3(X) -> otp_2979(X). + +otp_2979() -> + gn([[sparseDescr], [sparseStatus]]), + ?line expect(1, [{[sparseStr,0], "slut"}, + {[sparseStr,0], "slut"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3187 +%% Slogan: get-next on vacmAccessTable for colums > 5 returns +%% endOfTable - should return value. +%%----------------------------------------------------------------- +otp_3187(suite) -> []; +otp_3187(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + otp_3187(), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +otp_3187_2(X) -> otp_3187(X). + +otp_3187_3(X) -> otp_3187(X). + +otp_3187() -> + ?line Elements = + snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]), + lists:foreach(fun(E) -> + ?line if E == endOfTable -> + ?FAIL(endOfTable); + true -> ok + end + end, Elements). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3542 +%% Slogan: +%%----------------------------------------------------------------- +otp_3542(suite) -> []; +otp_3542(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_3542). + +otp_3542() -> + io:format("SNMP v3 discovery...~n"), + ?line Res = snmp_test_mgr:d(), + io:format("SNMP v3 discovery result: ~p~n",[Res]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-3725 +%% Slogan: Slow response time on snmpa:int_to_enum +%%----------------------------------------------------------------- +otp_3725(suite) -> []; +otp_3725(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_3725_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +%% Req. OLD-SNMPEA-MIB +otp_3725_test(MaNode) -> + io:format("Testing feature requested in ticket OTP-3725...~n"), + ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]), + ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]), + ?DBG("otp_3725_test -> Db = ~p",[Db]), + + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [Db, intAgentIpAddress]), + ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name, + [Db,OID]), + ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [Db, [1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [Db, intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum, + [Db, 'RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]), + ok. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-4394 +%% Slogan: Target mib tag list check invalid +%%----------------------------------------------------------------- + + +otp_4394(suite) -> {req, [], {conf, + init_otp_4394, + [otp_4394_test], + finish_otp_4394}}. + +init_otp_4394(Config) when list(Config) -> + ?DBG("init_otp_4394 -> entry with" + "~n Config: ~p", [Config]), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line otp_4394_config(AgentDir, MgrDir, Ip), + MasterAgentVerbosity = {master_agent_verbosity, trace}, + NetIfVerbosity = {net_if_verbosity, trace}, + Opts = [MasterAgentVerbosity,NetIfVerbosity], + [{vsn, v1} | start_v1_agent(Config,Opts)]. + +otp_4394_config(AgentDir, MgrDir, Ip0) -> + ?DBG("otp_4394_config -> entry with" + "~n AgentDir: ~p" + "~n MgrDir: ~p" + "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]), + Vsn = [v1], + Ip = tuple_to_list(Ip0), + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip, + ?TRAP_UDP, Ip, 4000, + "OTP-4394 test"), + ?line case update_usm(Vsn, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsn, MgrDir); + false -> + ?line ok + end, + C1 = {"a", "all-rights", "initial", "", "pc"}, + C2 = {"c", "secret", "secret_name", "", "secret_tag"}, + ?line write_community_conf(AgentDir, [C1, C2]), + ?line update_vacm(Vsn, AgentDir), + Ta1 = {"shelob v1", + [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda + "pc1", + "target_v1", "", + %% [255,255,255,255,0,0], + [], + 2048}, + Ta2 = {"bifur v1", + [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip + "pc2", + "target_v1", "", + %% [255,255,255,255,0,0], + [], 2048}, + ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]), + ?line write_target_params_conf(AgentDir, Vsn), + ?line write_notify_conf(AgentDir), + ok. + + + +finish_otp_4394(Config) when list(Config) -> + ?DBG("finish_otp_4394 -> entry", []), + C1 = stop_agent(Config), + delete_files(C1), + erase(mgr_node), + lists:keydelete(vsn, 1, C1). + +otp_4394_test(suite) -> []; +otp_4394_test(Config) -> + ?DBG("otp_4394_test -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_4394_test1), + ?DBG("otp_4394_test -> done", []), + ok. + +otp_4394_test1() -> + ?DBG("otp_4394_test1 -> entry", []), + gn([[1,1]]), + Res = + case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of + %% {error, 1, {"?",[]}, {"~w",[timeout]}} + {error, 1, _, {_, [timeout]}} -> + ?DBG("otp_4394_test1 -> expected result: timeout", []), + ok; + Else -> + Else + end, + ?DBG("otp_4394_test1 -> done with: ~p", [Res]), + Res. + + +%%%-------------------------------------------------- +%%% Used to test the standard mib with our +%%% configuration. +%%%-------------------------------------------------- +run(F, A, Opts) -> + M = get(mib_dir), + Dir = get(mgr_dir), + User = snmp_misc:get_option(user, Opts, "all-rights"), + SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv), + EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"), + CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID), + Community = snmp_misc:get_option(community, Opts, "all-rights"), + ?DBG("run -> start crypto app",[]), + Crypto = case os:type() of + vxworks -> + no_crypto; + _ -> + ?CRYPTO_START() + end, + ?DBG("run -> Crypto: ~p",[Crypto]), + catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + ?DBG("run -> config:~n" + "\tM: ~p~n" + "\tDir: ~p~n" + "\tUser: ~p~n" + "\tSecLevel: ~p~n" + "\tEngineID: ~p~n" + "\tCtxEngineID: ~p~n" + "\tCommunity: ~p~n" + "\tStdM: ~p", + [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]), + case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()}, + {packet_server_debug,true}, + {debug,true}, + {agent, get(master_host)}, + {agent_udp, 4000}, + {trap_udp, 5000}, + {recbuf,65535}, + quiet, + get(vsn), + {community, Community}, + {user, User}, + {sec_level, SecLevel}, + {engine_id, EngineID}, + {context_engine_id, CtxEngineID}, + {dir, Dir}, + {mibs, mibs(StdM, M)}]) of + {ok, _Pid} -> + Res = apply(?MODULE, F, A), + catch snmp_test_mgr:stop(), + Res; + Err -> + io:format("Error starting manager: ~p\n", [Err]), + catch snmp_test_mgr:stop(), + ?line exit({mgr_start, Err}) + end. + + +mibs(StdMibDir,MibDir) -> + [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")), + join(MibDir, "OLD-SNMPEA-MIB.bin"), + join(StdMibDir, "SNMP-FRAMEWORK-MIB"), + join(StdMibDir, "SNMP-MPD-MIB"), + join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"), + join(StdMibDir, "SNMP-USER-BASED-SM-MIB"), + join(StdMibDir, "SNMP-TARGET-MIB"), + join(StdMibDir, "SNMP-NOTIFICATION-MIB"), + join(MibDir, "Klas1.bin"), + join(MibDir, "Klas2.bin"), + join(MibDir, "Klas3.bin"), + join(MibDir, "Klas4.bin"), + join(MibDir, "SA-MIB.bin"), + join(MibDir, "TestTrap.bin"), + join(MibDir, "Test1.bin"), + join(MibDir, "Test2.bin"), + join(MibDir, "TestTrapv2.bin")]. + +join(D,F) -> + filename:join(D,F). + +%% string used in index +is(S) -> [length(S) | S]. + +try_test(Func) -> + call(get(mgr_node), ?MODULE, run, [Func, [], []]). + +try_test(Func, A) -> + call(get(mgr_node), ?MODULE, run, [Func, A, []]). + +try_test(Func, A, Opts) -> + call(get(mgr_node), ?MODULE, run, [Func, A, Opts]). + +call(N,M,F,A) -> + ?DBG("call -> entry with~n" + " N: ~p~n" + " M: ~p~n" + " F: ~p~n" + " A: ~p~n" + " when~n" + " get(): ~p", + [N,M,F,A,get()]), + spawn(N, ?MODULE, wait, [self(),get(),M,F,A]), + receive + {done, {'EXIT', Rn}, Loc} -> + ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]), + put(test_server_loc, Loc), + exit(Rn); + {done, Ret, Zed} -> + ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]), + Ret + end. + +wait(From, Env, M, F, A) -> + ?DBG("wait -> entry with ~n" + "\tFrom: ~p~n" + "\tEnv: ~p",[From,Env]), + lists:foreach(fun({K,V}) -> put(K,V) end, Env), + Rn = (catch apply(M, F, A)), + ?DBG("wait -> Rn: ~n~p", [Rn]), + From ! {done, Rn, get(test_server_loc)}, + exit(Rn). + +expect(A,B) -> ok = snmp_test_mgr:expect(A,B). +expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C). +expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D). +expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F). + +get_req(Id, Vars) -> + ?DBG("get_req -> entry with~n" + "\tId: ~p~n" + "\tVars: ~p",[Id,Vars]), + g(Vars), + ?DBG("get_req -> await response",[]), + {ok, Val} = snmp_test_mgr:get_response(Id, Vars), + ?DBG("get_req -> response: ~p",[Val]), + Val. + +get_next_req(Vars) -> + ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]), + gn(Vars), + ?DBG("get_next_req -> await response",[]), + Response = snmp_test_mgr:receive_response(), + ?DBG("get_next_req -> response: ~p",[Response]), + Response. + + + +start_node(Name) -> + ?LOG("start_node -> entry with Name: ~p",[Name]), + M = list_to_atom(?HOSTNAME(node())), + ?DBG("start_node -> M: ~p",[M]), + Pa = filename:dirname(code:which(?MODULE)), + ?DBG("start_node -> Pa: ~p",[Pa]), + + Args = case init:get_argument('CC_TEST') of + {ok, [[]]} -> + " -pa /clearcase/otp/libraries/snmp/ebin "; + {ok, [[Path]]} -> + " -pa " ++ Path; + error -> + "" + end, + %% Do not use start_link!!! (the proc that calls this one is tmp) + ?DBG("start_node -> Args: ~p~n",[Args]), + A = Args ++ " -pa " ++ Pa, + case (catch ?START_NODE(Name, A)) of + {ok, Node} -> + %% Tell the test_server to not clean up things it never started. + ?DBG("start_node -> Node: ~p",[Node]), + {ok, Node}; + Else -> + ?ERR("start_node -> failed with(other): Else: ~p",[Else]), + ?line ?FAIL(Else) + end. + + +stop_node(Node) -> + ?LOG("stop_node -> Node: ~p",[Node]), + rpc:cast(Node, erlang, halt, []). + +p(X) -> + io:format(user, X++"\n", []). + +sleep(X) -> + receive + after + X -> ok + end. + +%%%----------------------------------------------------------------- +%%% Configuration +%%%----------------------------------------------------------------- +config(Vsns, MgrDir, AgentDir, MIp, AIp) -> + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp, + ?TRAP_UDP, AIp, 4000, + "test"), + ?line case update_usm(Vsns, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsns, MgrDir); + false -> + ?line ok + end, + ?line update_community(Vsns, AgentDir), + ?line update_vacm(Vsns, AgentDir), + ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns), + ?line write_target_params_conf(AgentDir, Vsns), + ?line write_notify_conf(AgentDir), + ok. + +delete_files(Config) -> + Dir = ?config(agent_dir, Config), + {ok, List} = file:list_dir(Dir), + lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end, + List). + +update_usm(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +update_usm_mgr(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +rewrite_usm_mgr(Dir, ShaKey, DesKey) -> + ?line ok = file:rename(filename:join(Dir,"usm.conf"), + filename:join(Dir,"usm.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + file:close(Fid). + +reset_usm_mgr(Dir) -> + ?line ok = file:rename(filename:join(Dir,"usm.old"), + filename:join(Dir,"usm.conf")). + + +update_community([v3], _Dir) -> ok; +update_community(_, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n", + []), + file:close(Fid). + + +-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]). +update_vacm(_Vsn, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]), + ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", " + "~w, excluded, null}.\n", [?tDescr_instance]), + file:close(Fid). + + +vacm_ver(v1) -> v1; +vacm_ver(v2) -> v2c; +vacm_ver(v3) -> usm. + + +write_community_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write), + ok = write_community_conf1(Fid, Confs), + file:close(Fid). + +write_community_conf1(_, []) -> + ok; +write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) -> + ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n", + [ComIdx, ComName, SecName, CtxName, TransTag]), + write_community_conf1(Fid, Confs). + + +write_target_addr_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + ok = write_target_addr_conf1(Fid, Confs), + file:close(Fid). + + +write_target_addr_conf1(_, []) -> + ok; +write_target_addr_conf1(Fid, + [{Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz}|Confs]) -> + ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", + [Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz]), + write_target_addr_conf1(Fid, Confs). + +write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + lists:foreach(fun(Vsn) -> + ok = io:format(Fid, + "{\"~s\", ~w, ~w, 1500, 3, " + "\"std_trap\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, mk_param(Vsn)]), + case Vsn of + v1 -> ok; + v2 -> + ok = io:format(Fid, + "{\"~s.2\",~w,~w,1500,3, " + "\"std_inform\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]); + v3 -> + ok = io:format(Fid, + "{\"~s.3\",~w,~w,1500,3, " + "\"std_inform\", \"~s\", " + "\"mgrEngine\", [], 1024}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]) + end + end, + Vsns), + file:close(Fid). + +mk_param(v1) -> "target_v1"; +mk_param(v2) -> "target_v2"; +mk_param(v3) -> "target_v3". + +mk_ip([A,B,C,D], Vsn) -> + io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]). + + +rewrite_target_addr_conf(Dir,NewPort) -> + TAFile = filename:join(Dir, "target_addr.conf"), + ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]), + case file:read_file_info(TAFile) of + {ok, _} -> ok; + {error, R} -> ?ERR("failure reading file info of " + "target address config file: ~p",[R]), + ok + end, + + ?line [TrapAddr|Addrs] = + snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end), + + ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]), + + NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs], + + ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]), + + ?line ok = file:rename(filename:join(Dir,"target_addr.conf"), + filename:join(Dir,"target_addr.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + + ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs), + + file:close(Fid). + +rewrite_target_addr_conf1(O) -> + {ok,O}. + +rewrite_target_addr_conf2(NewPort,{Name,Ip,_Port,Timeout,Retry, + "std_trap",EngineId}) -> + ?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]), + {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; +rewrite_target_addr_conf2(_NewPort,O) -> + ?LOG("rewrite_target_addr_conf2 -> entry with " + "~n O: ~p",[O]), + O. + + +rewrite_target_addr_conf3(_,[]) -> ok; +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry, + ParamName,EngineId}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % ParamsName + "\"~s\"}.", % EngineId + [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]), + rewrite_target_addr_conf3(Fid,T); +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList, + ParamName,EngineId,TMask,MMS}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % TagList + "\"~s\", " % ParamsName + "\"~s\"," % EngineId + "~p, " % TMask + "~p}.", % MMS + [Name,Ip,Port,Timeout,Retry,TagList,ParamName, + EngineId,TMask,MMS]), + rewrite_target_addr_conf3(Fid,T). + +reset_target_addr_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_addr.old"), + filename:join(Dir,"target_addr.conf")). + +write_target_params_conf(Dir, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + lists:foreach(fun(Vsn) -> + MP = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> v3 + end, + SM = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> usm + end, + ok = io:format(Fid, "{\"target_~w\", ~w, ~w, " + "\"all-rights\", noAuthNoPriv}.~n", + [Vsn, MP, SM]) + end, + Vsns), + file:close(Fid). + +rewrite_target_params_conf(Dir, SecName, SecLevel) -> + ?line ok = file:rename(filename:join(Dir,"target_params.conf"), + filename:join(Dir,"target_params.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n", + [SecName, SecLevel]), + file:close(Fid). + +reset_target_params_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_params.old"), + filename:join(Dir,"target_params.conf")). + +write_notify_conf(Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write), + ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []), + ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []), + file:close(Fid). + +ver_to_trap_str([v1]) -> "v1"; +ver_to_trap_str([v2]) -> "v2"; +% default is to use the latest snmp version +ver_to_trap_str([v1,v2]) -> "v2". + + + +write_view_conf(Dir) -> + {ok, Fid} = file:open(a(Dir,"view.conf"),write), + ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []), + ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]), + file:close(Fid). + +a(A,B) -> lists:append(A,B). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +copy_file(From, To) -> + {ok, Bin} = file:read_file(From), + ok = file:write_file(To, Bin). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +display_memory_usage() -> + Info = snmpa:info(snmp_master_agent), + TreeSize = lists_key1search(tree_size_bytes, Info), + ProcMem = lists_key1search(process_memory, Info), + MibDbSize = lists_key1search([db_memory,mib], Info), + NodeDbSize = lists_key1search([db_memory,node], Info), + TreeDbSize = lists_key1search([db_memory,tree], Info), + ?INF("Memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p", + [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]). + +lists_key1search([], Res) -> + Res; +lists_key1search([Key|Keys], List) when atom(Key), list(List) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + lists_key1search(Keys, Val); + false -> + undefined + end; +lists_key1search(Key, List) when atom(Key) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + Val; + false -> + undefined + end. + + +regs() -> + lists:sort(registered()). diff --git a/lib/snmp/test/snmp_agent_mibs_test.erl b/lib/snmp/test/snmp_agent_mibs_test.erl new file mode 100644 index 0000000000..5f1ff53a79 --- /dev/null +++ b/lib/snmp/test/snmp_agent_mibs_test.erl @@ -0,0 +1,721 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: +%%---------------------------------------------------------------------- +-module(snmp_agent_mibs_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-include_lib("snmp/include/snmp_types.hrl"). +-include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl"). +-include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl"). +-include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl"). +-include("snmp_test_data/Test2.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + all/1, + init_per_testcase/2, fin_per_testcase/2, + init_all/1, finish_all/1, + + start_and_stop/1, + size_check/1, + size_check_ets/1, + size_check_dets/1, + size_check_mnesia/1, + load_unload/1, + me_lookup/1, + which_mib/1, + cache_test/1 + + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + ]). + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(size_check_dets, Config) when is_list(Config) -> + Dir = ?config(priv_dir, Config), + DetsDir = join(Dir, "dets_dir/"), + ?line ok = file:make_dir(DetsDir), + [{dets_dir, DetsDir}|Config]; +init_per_testcase(size_check_mnesia, Config) when is_list(Config) -> + Dir = ?config(priv_dir, Config), + MnesiaDir = join(Dir, "mnesia_dir/"), + ?line ok = file:make_dir(MnesiaDir), + mnesia_start([{dir, MnesiaDir}]), + [{mnesia_dir, MnesiaDir}|Config]; +init_per_testcase(cache_test, Config) when is_list(Config) -> + Min = timer:minutes(5), + Timeout = + case lists:keysearch(tc_timeout, 1, Config) of + {value, {tc_timeout, TcTimeout}} when TcTimeout < Min -> + Min; + {value, {tc_timeout, TcTimeout}} -> + TcTimeout; + _ -> + Min + end, + Dog = test_server:timetrap(Timeout), + [{watchdog, Dog} | Config]; +init_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +fin_per_testcase(size_check_dets, Config) when is_list(Config) -> + Dir = ?config(dets_dir, Config), + ?line ok = ?DEL_DIR(Dir), + lists:keydelete(dets_dir, 1, Config); +fin_per_testcase(size_check_mnesia, Config) when is_list(Config) -> + mnesia_stop(), + Dir = ?config(mnesia_dir, Config), + ?line ok = ?DEL_DIR(Dir), + lists:keydelete(mnesia_dir, 1, Config); +fin_per_testcase(cache_test, Config) when is_list(Config) -> + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + Config; +fin_per_testcase(_Case, Config) when is_list(Config) -> + Config. + + +%%====================================================================== +%% Test case definitions +%%====================================================================== + +all(suite) -> + {conf, init_all, cases(), finish_all}. + +cases() -> + [ + start_and_stop, + load_unload, + size_check, + me_lookup, + which_mib, + cache_test + ]. + +init_all(Config) when is_list(Config) -> + %% Data dir points wrong + DataDir0 = ?config(data_dir, Config), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + [{snmp_data_dir, DataDir ++ "/"}|Config]. + +finish_all(Config) when is_list(Config) -> + lists:keydelete(snmp_data_dir, 1, Config). + + +%%====================================================================== +%% Test functions +%%====================================================================== + +start_and_stop(suite) -> []; +start_and_stop(Config) when is_list(Config) -> + Prio = normal, + Verbosity = trace, + + ?line sym_start(Prio, Verbosity), + ?line MibsPid = mibs_start(Prio, Verbosity), + + ?line mibs_info(MibsPid), + + ?line mibs_stop(MibsPid), + ?line sym_stop(), + + ok. + + +%% --------------------------------------------------------------------- + +load_unload(suite) -> []; +load_unload(Config) when is_list(Config) -> + Prio = normal, + Verbosity = log, + %% MibStorage = ets, + MibDir = ?config(snmp_data_dir, Config), + + ?DBG("load_unload -> start symbolic store", []), + ?line sym_start(Prio, Verbosity), + + ?DBG("load_unload -> start mib server", []), + ?line MibsPid = mibs_start(Prio, Verbosity), + + ?DBG("load_unload -> load one not already loaded mib", []), + ?line ok = verify_loaded_mibs(MibsPid, MibDir, []), + ?line ok = load_mibs(MibsPid, MibDir, ["Test2"]), + ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["Test2"]), + + ?DBG("load_unload -> load one already loaded mib", []), + ?line {error, _} = load_mibs(MibsPid, MibDir, ["Test2"]), + + ?DBG("load_unload -> load 2 not already loaded mibs", []), + ?line ok = load_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]), + ?line ok = verify_loaded_mibs(MibsPid, MibDir, + ["Test2", "TestTrap", "TestTrapv2"]), + + ?DBG("load_unload -> unload one loaded mib", []), + ?line ok = unload_mibs(MibsPid, ["Test2"]), + ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrap", "TestTrapv2"]), + + ?DBG("load_unload -> try unload two loaded mibs and one not loaded", []), + ?line {error, _} = unload_mibs(MibsPid, ["TestTrap","Test2","TestTrapv2"]), + ?line ok = verify_loaded_mibs(MibsPid, MibDir, ["TestTrapv2"]), + + ?DBG("load_unload -> unload the remaining loaded mib", []), + ?line ok = unload_mibs(MibsPid, ["TestTrapv2"]), + ?line ok = verify_loaded_mibs(MibsPid, MibDir, []), + + ?DBG("load_unload -> stop mib server", []), + ?line mibs_stop(MibsPid), + + ?DBG("load_unload -> stop symbolic store", []), + ?line sym_stop(), + + ok. + + +%% --------------------------------------------------------------------- + +size_check(suite) -> + [ + size_check_ets, + size_check_dets, + size_check_mnesia + ]. + +size_check_ets(suite) -> + []; +size_check_ets(Config) when is_list(Config) -> + do_size_check([{mib_storage, ets}|Config]). + +size_check_dets(suite) -> + []; +size_check_dets(Config) when is_list(Config) -> + Dir = ?config(dets_dir, Config), + do_size_check([{mib_storage, {dets, Dir}}|Config]). + +size_check_mnesia(suite) -> + []; +size_check_mnesia(Config) when is_list(Config) -> + do_size_check([{mib_storage, {mnesia, [node()]}}|Config]). + +do_size_check(Config) -> + ?DBG("do_size_check -> start", []), + Prio = normal, + Verbosity = trace, + + MibStorage = ?config(mib_storage, Config), + ?DBG("do_size_check -> MibStorage: ~p", [MibStorage]), + MibDir = ?config(snmp_data_dir, Config), + StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + + ?DBG("do_size_check -> start symbolic store", []), + ?line sym_start(Prio, MibStorage, Verbosity), + ?DBG("do_size_check -> start mib server", []), + ?line MibsPid = mibs_start(Prio, MibStorage, Verbosity), + + Mibs = ["Test2", "TestTrap", "TestTrapv2"], + StdMibs = ["OTP-SNMPEA-MIB", + "SNMP-COMMUNITY-MIB", + "SNMP-FRAMEWORK-MIB", + "SNMP-MPD-MIB", + "SNMP-NOTIFICATION-MIB", + "SNMP-TARGET-MIB", + "SNMP-USER-BASED-SM-MIB", + "SNMP-VIEW-BASED-ACM-MIB", + "SNMPv2-MIB", + "SNMPv2-TC", + "SNMPv2-TM"], + + ?DBG("do_size_check -> load mibs", []), + ?line load_mibs(MibsPid, MibDir, Mibs), + ?DBG("do_size_check -> load std mibs", []), + ?line load_mibs(MibsPid, StdMibDir, StdMibs), + + ?SLEEP(2000), + ?DBG("do_size_check -> display mem usage", []), + ?line display_memory_usage(MibsPid), + + ?DBG("do_size_check -> unload std mibs", []), + ?line unload_mibs(MibsPid, StdMibs), + ?DBG("do_size_check -> unload mibs", []), + ?line unload_mibs(MibsPid, Mibs), + + ?DBG("do_size_check -> stop mib server", []), + ?line mibs_stop(MibsPid), + ?DBG("do_size_check -> stop symbolic store", []), + ?line sym_stop(), + + ?DBG("do_size_check -> done", []), + ok. + + +%% --------------------------------------------------------------------- + +me_lookup(suite) -> []; +me_lookup(Config) when is_list(Config) -> + Prio = normal, + Verbosity = trace, + %% MibStorage = ets, + MibDir = ?config(snmp_data_dir, Config), + StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + Mibs = ["Test2", "TestTrap", "TestTrapv2"], + StdMibs = ["OTP-SNMPEA-MIB", + "SNMP-COMMUNITY-MIB", + "SNMP-FRAMEWORK-MIB", + "SNMP-MPD-MIB", + "SNMP-NOTIFICATION-MIB", + "SNMP-TARGET-MIB", + %% "SNMP-USER-BASED-SM-MIB", + "SNMP-VIEW-BASED-ACM-MIB", + "SNMPv2-MIB", + "SNMPv2-TC", + "SNMPv2-TM"], + + ?DBG("me_lookup -> start symbolic store", []), + ?line sym_start(Prio, Verbosity), + + ?DBG("me_lookup -> start mib server", []), + ?line MibsPid = mibs_start(Prio, Verbosity), + + ?DBG("me_lookup -> load mibs", []), + ?line load_mibs(MibsPid, MibDir, Mibs), + ?DBG("me_lookup -> load std mibs", []), + ?line load_mibs(MibsPid, StdMibDir, StdMibs), + + ?DBG("me_lookup -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = me_lookup(MibsPid, ?snmpTrapCommunity_instance), + + ?DBG("me_lookup -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = me_lookup(MibsPid, ?vacmViewSpinLock_instance), + + ?DBG("me_lookup -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = me_lookup(MibsPid, ?usmStatsNotInTimeWindows_instance), + + ?DBG("me_lookup -> stop mib server", []), + ?line mibs_stop(MibsPid), + + ?DBG("me_lookup -> stop symbolic store", []), + ?line sym_stop(), + + ok. + + +%% --------------------------------------------------------------------- + +which_mib(suite) -> []; +which_mib(Config) when is_list(Config) -> + Prio = normal, + Verbosity = trace, + %% MibStorage = ets, + MibDir = ?config(snmp_data_dir, Config), + StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + Mibs = ["Test2", "TestTrap", "TestTrapv2"], + StdMibs = ["OTP-SNMPEA-MIB", + "SNMP-COMMUNITY-MIB", + "SNMP-FRAMEWORK-MIB", + "SNMP-MPD-MIB", + "SNMP-NOTIFICATION-MIB", + "SNMP-TARGET-MIB", + %% "SNMP-USER-BASED-SM-MIB", + "SNMP-VIEW-BASED-ACM-MIB", + "SNMPv2-MIB", + "SNMPv2-TC", + "SNMPv2-TM"], + + ?DBG("which_mib -> start symbolic store", []), + ?line sym_start(Prio, Verbosity), + + ?DBG("which_mib -> start mib server", []), + ?line MibsPid = mibs_start(Prio, Verbosity), + + ?DBG("which_mib -> load mibs", []), + ?line load_mibs(MibsPid, MibDir, Mibs), + ?DBG("which_mib -> load std mibs", []), + ?line load_mibs(MibsPid, StdMibDir, StdMibs), + + ?DBG("which_mib -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = which_mib(MibsPid, ?snmpTrapCommunity_instance, + "SNMP-COMMUNITY-MIB"), + + ?DBG("which_mib -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = which_mib(MibsPid, ?vacmViewSpinLock_instance, + "SNMP-VIEW-BASED-ACM-MIB"), + + ?DBG("which_mib -> find ~w from SNMP-USER-BASED-SM-MIB (not loaded)", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = which_mib(MibsPid, ?usmStatsNotInTimeWindows_instance, + "SNMP-USER-BASED-SM-MIB"), + + ?DBG("which_mib -> stop mib server", []), + ?line mibs_stop(MibsPid), + + ?DBG("which_mib -> stop symbolic store", []), + ?line sym_stop(), + + ok. + + +%% --------------------------------------------------------------------- + +cache_test(suite) -> []; +cache_test(Config) when is_list(Config) -> + ?DBG("cache_test -> start", []), + Prio = normal, + Verbosity = trace, + MibStorage = ets, + MibDir = ?config(snmp_data_dir, Config), + StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + Mibs = ["Test2", "TestTrap", "TestTrapv2"], + StdMibs = ["OTP-SNMPEA-MIB", + "SNMP-COMMUNITY-MIB", + "SNMP-FRAMEWORK-MIB", + "SNMP-MPD-MIB", + "SNMP-NOTIFICATION-MIB", + "SNMP-TARGET-MIB", + %% "SNMP-USER-BASED-SM-MIB", + "SNMP-VIEW-BASED-ACM-MIB", + "SNMPv2-MIB", + "SNMPv2-TC", + "SNMPv2-TM"], + + ?DBG("cache_test -> start symbolic store", []), + ?line sym_start(Prio, MibStorage, Verbosity), + + ?DBG("cache_test -> start mib server", []), + GcLimit = 2, + Age = timer:seconds(10), + CacheOpts = [{autogc, false}, {age, Age}, {gclimit, GcLimit}], + ?line MibsPid = mibs_start(Prio, MibStorage, [], Verbosity, CacheOpts), + + ?DBG("cache_test -> load mibs", []), + ?line load_mibs(MibsPid, MibDir, Mibs), + ?DBG("cache_test -> load std mibs", []), + ?line load_mibs(MibsPid, StdMibDir, StdMibs), + + ?DBG("cache_test -> do a simple walk to populate the cache", []), + ?line ok = walk(MibsPid), + + {ok, Sz1} = snmpa_mib:which_cache_size(MibsPid), + ?DBG("cache_test -> Size1: ~p", [Sz1]), + + ?DBG("cache_test -> sleep 5 secs", []), + ?SLEEP(timer:seconds(5)), + + ?DBG("cache_test -> perform gc, expect nothing", []), + {ok, 0} = snmpa_mib:gc_cache(MibsPid), + + ?DBG("cache_test -> sleep 10 secs", []), + ?SLEEP(timer:seconds(10)), + + ?DBG("cache_test -> perform gc, expect GcLimit", []), + GcLimit1 = GcLimit + 1, + {ok, GcLimit1} = snmpa_mib:gc_cache(MibsPid, Age, GcLimit1), + + Sz2 = Sz1 - GcLimit1, + {ok, Sz2} = snmpa_mib:which_cache_size(MibsPid), + ?DBG("cache_test -> Size2: ~p", [Sz2]), + + ?DBG("cache_test -> enable cache autogc", []), + ?line ok = snmpa_mib:enable_cache_autogc(MibsPid), + + ?DBG("cache_test -> wait 65 seconds to allow gc to happen", []), + ?SLEEP(timer:seconds(65)), + Sz3 = Sz2 - GcLimit, + {ok, Sz3} = snmpa_mib:which_cache_size(MibsPid), + ?DBG("cache_test -> Size3: ~p", [Sz3]), + + ?DBG("cache_test -> " + "wait 2 minutes to allow gc to happen, expect empty cache", []), + ?SLEEP(timer:minutes(2)), + {ok, 0} = snmpa_mib:which_cache_size(MibsPid), + + ?DBG("cache_test -> stop mib server", []), + ?line mibs_stop(MibsPid), + + ?DBG("cache_test -> stop symbolic store", []), + ?line sym_stop(), + ok. + +walk(MibsPid) -> + MibView = snmpa_acm:get_root_mib_view(), + do_walk(MibsPid, ?snmpTrapCommunity_instance, MibView), + do_walk(MibsPid, ?vacmViewSpinLock_instance, MibView), + do_walk(MibsPid, ?usmStatsNotInTimeWindows_instance, MibView), + do_walk(MibsPid, ?tDescr_instance, MibView). + + +do_walk(MibsPid, Oid, MibView) -> + io:format("do_walk -> entry with" + "~n Oid: ~p" + "~n", [Oid]), + case snmpa_mib:next(MibsPid, Oid, MibView) of + {table, _, _, #me{oid = Oid}} -> + ok; + {table, _, _, #me{oid = Next}} -> + do_walk(MibsPid, Next, MibView); + {variable, #me{oid = Oid}, _} -> + ok; + {variable, #me{oid = Next}, _} -> + do_walk(MibsPid, Next, MibView) + end. + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +%% -- Mnesia functions + +mnesia_start(Opts) -> + mnesia_start(Opts, [node()]). + +mnesia_start(Opts, Nodes) -> + ?DBG("mnesia_start -> load mnesia", []), + ?line ok = application:load(mnesia), + F = fun({Key, Val}) -> + ?DBG("mnesia_start -> set mnesia env: ~n~p -> ~p", [Key,Val]), + ?line application_controller:set_env(mnesia, Key, Val) + end, + lists:foreach(F, Opts), + ?DBG("mnesia_start -> create mnesia schema on ~p", [Nodes]), + ?line ok = mnesia:create_schema(Nodes), + ?DBG("mnesia_start -> start mnesia", []), + ?line ok = application:start(mnesia), + ok. + +mnesia_stop() -> + ?DBG("mnesia_stop -> stop mnesia", []), + application:stop(mnesia), + ?DBG("mnesia_stop -> unload mnesia", []), + application:unload(mnesia), + ok. + +%% - Symbolic Store mini interface + +sym_start(Prio, Verbosity) -> + sym_start(Prio, ets, Verbosity). + +sym_start(Prio, MibStorage, Verbosity) -> + Opts = [{mib_storage, MibStorage}, {verbosity,Verbosity}], + {ok, _Pid} = snmpa_symbolic_store:start_link(Prio, Opts), + ok. + +sym_stop() -> + ok = snmpa_symbolic_store:stop(). + +sym_info() -> + snmpa_symbolic_store:info(). + + +%% -- MIB server mini interface + +mibs_start(Prio, Verbosity) when is_atom(Prio) andalso is_atom(Verbosity) -> + mibs_start(Prio, ets, [], Verbosity). + +mibs_start(Prio, MibStorage, Verbosity) + when is_atom(Prio) andalso is_atom(Verbosity) -> + mibs_start(Prio, MibStorage, [], Verbosity). + +mibs_start(Prio, MibStorage, Mibs, Verbosity) + when is_atom(Prio) andalso + is_list(Mibs) andalso + is_atom(Verbosity) -> + mibs_start(Prio, MibStorage, Mibs, Verbosity, []). + +mibs_start(Prio, MibStorage, Mibs, Verbosity, CacheOpts) + when is_atom(Prio) andalso + is_list(Mibs) andalso + is_atom(Verbosity) andalso + is_list(CacheOpts) -> + Opts = [{mib_storage, MibStorage}, + {verbosity, Verbosity}, + {cache, CacheOpts}], + {ok, Pid} = snmpa_mib:start_link(Prio, Mibs, Opts), + Pid. + +mibs_stop(Pid) -> + ok = snmpa_mib:stop(Pid). + +mibs_info(Pid) -> + snmpa_mib:info(Pid). + +load_mibs(Pid, Dir, Mibs0) -> + Mibs = [join(Dir, Mib) || Mib <- Mibs0], + snmpa_mib:load_mibs(Pid, Mibs). + +unload_mibs(Pid, Mibs) -> + snmpa_mib:unload_mibs(Pid, Mibs). + +verify_loaded_mibs(Pid, Dir, ExpectedMibs0) -> + ExpectedMibs = [join(Dir, Mib) || Mib <- ExpectedMibs0], + case snmpa_mib:info(Pid, loaded_mibs) of + ExpectedMibs -> + ok; + LoadedMibs0 -> + ?DBG("verify_loaded_mibs -> LoadedMibs0: ~p", [LoadedMibs0]), + LoadedMibs = [filename:rootname(FN, ".bin") || FN <- LoadedMibs0], + ?DBG("verify_loaded_mibs -> LoadedMibs: ~p", [LoadedMibs]), + ExpNotLoadedMibs = ExpectedMibs -- LoadedMibs, + LoadedNotExpMibs = LoadedMibs -- ExpectedMibs, + ?DBG("verify_loaded_mibs -> " + "~n ExpNotLoadedMibs: ~p" + "~n LoadedNotExpMibs: ~p", + [ExpNotLoadedMibs, LoadedNotExpMibs]), + case ExpNotLoadedMibs of + [] -> + case LoadedNotExpMibs of + [] -> + ok; + _ -> + {error, {unexpected_loaded_mibs, LoadedNotExpMibs}} + end; + _ -> + case LoadedNotExpMibs of + [] -> + {error, {not_loaded_mibs, ExpNotLoadedMibs}}; + _ -> + {error, {unexpected_mibs, + ExpNotLoadedMibs, LoadedNotExpMibs}} + end + end + + end. + +me_lookup(Pid, Oid) -> + case snmpa_mib:lookup(Pid, Oid) of + {variable, #me{oid = Oid}} -> + ok; + {variable, #me{oid = OtherOid}} -> + case lists:reverse(Oid) of + [0|Rest] -> + case lists:reverse(Rest) of + OtherOid -> + ok; + AnotherOid -> + {error, {invalid_oid, Oid, AnotherOid}} + end; + _ -> + {error, {invalid_oid, Oid, OtherOid}} + end; + {table_column, _ME, _TableEntryOid} -> + ok; + {subagent, SubAgentPid, _SANextOid} -> + {error, {subagent, SubAgentPid}}; + {false, Reason} -> + {error, Reason}; + Else -> + {error, Else} + end. + + +which_mib(Pid, Oid, Mib1) -> + case snmpa_mib:which_mib(Pid, Oid) of + {ok, Mib2} when is_atom(Mib2) -> + Mib3 = atom_to_list(Mib2), + which_mib(Mib1, Mib3); + {ok, Mib2} -> + which_mib(Mib1, Mib2); + {error, Reason} -> + {error, Reason}; + Else -> + {error, Else} + end. + +which_mib(M, M) -> + ok; +which_mib(M1, M2) -> + {error, {invalid_mib, M1, M2}}. + + +%% -- + +display_memory_usage(MibsPid) -> + SymInfo = sym_info(), + SymProcSize = key1search(process_memory, SymInfo), + DbSize = key1search(db_memory, SymInfo), + MibsInfo = mibs_info(MibsPid), + TreeSize = key1search(tree_size_bytes, MibsInfo), + MibsProcMem = key1search(process_memory, MibsInfo), + MibDbSize = key1search([db_memory,mib], MibsInfo), + NodeDbSize = key1search([db_memory,node], MibsInfo), + TreeDbSize = key1search([db_memory,tree], MibsInfo), + ?INF("Symbolic store memory usage: " + "~n Process memory size: ~p" + "~n Db size: ~p" + "~n" + "~nMib server memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p" + "~n", + [SymProcSize, DbSize, + TreeSize, MibsProcMem, MibDbSize, NodeDbSize, TreeDbSize]). + +key1search([], Res) -> + Res; +key1search([Key|Keys], List) when is_atom(Key) andalso is_list(List) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + key1search(Keys, Val); + false -> + undefined + end; +key1search(Key, List) when is_atom(Key) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + Val; + false -> + undefined + end. + +join(Dir, File) -> + filename:join(Dir, File). diff --git a/lib/snmp/test/snmp_agent_ms_test.erl b/lib/snmp/test/snmp_agent_ms_test.erl new file mode 100644 index 0000000000..3a3a790e6a --- /dev/null +++ b/lib/snmp/test/snmp_agent_ms_test.erl @@ -0,0 +1,5657 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_agent_ms_test). + +%% TODO +%% * Test fault-tolerance (kill master etc) +%% + +-compile(export_all). + +-define(application, snmp). + +-include_lib("kernel/include/file.hrl"). +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). +%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl"). + + +-define(klas1, [1,3,6,1,2,1,7]). +-define(klas2, [1,3,6,1,2,1,9]). +-define(klas3, [1,3,6,1,2,1,8,1]). +-define(klas4, [1,3,6,1,2,1,8,4]). +-define(sa, [1,3,6,1,4,1,193,2]). +-define(system, [1,3,6,1,2,1,1]). +-define(snmp, [1,3,6,1,2,1,11]). +-define(snmpTraps, [1,3,6,1,6,3,1,1,5]). +-define(ericsson, [1,3,6,1,4,1,193]). +-define(testTrap, [1,3,6,1,2,1,15,0]). +-define(xDescr, [1,3,6,1,2,1,17,1]). +-define(xDescr2, [1,3,6,1,2,1,17,2]). + +-define(active, 1). +-define(notInService, 2). +-define(notReady, 3). +-define(createAndGo, 4). +-define(createAndWait, 5). +-define(destroy, 6). + +-define(TRAP_UDP, 5000). + +-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"). + +-define(str(X), snmp_pdus:bits_to_str(X)). + +-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n", + [?LINE, self()]), + receive cont -> ok end + end). + + +-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]). +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + +-define(v1_2_3(V1,V2,V3), + case get(vsn) of + v1 -> V1; + v2 -> V2; + _ -> V3 + end). + +all(suite) -> {req, + [mnesia, distribution, + {local_slave_nodes, 2}, {time, 360}], + [{conf, init_all, cases(), finish_all}]}. + +init_per_testcase(_Case, Config) when list(Config) -> + Dog = ?t:timetrap(?t:minutes(6)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + Config. + +cases() -> + case ?OSTYPE() of + vxworks -> + %% No crypto app, so skip v3 testcases + [ + app_info, + test_v1, test_v2, test_v1_v2, + test_multi_threaded, + mib_storage, + tickets]; + _Else -> + [ + app_info, + test_v1, test_v2, test_v1_v2, test_v3, + test_multi_threaded, + mib_storage, + tickets + ] + end. + + +%%%----------------------------------------------------------------- +%%% The test case structure is as follows: +%%% +%%% init_all - starts mnesia, +%%% +%%% init_v1 - starts agent +%%% simple +%%% big - e.g. starts/stops subagent, load/unloads mibs +%%% init_mul +%%% mul_get +%%% mul_set +%%% <etc> +%%% finish_mul +%%% <etc> +%%% finish_v1 +%%% +%%% init_v2 - starts agent +%%% finish_v2 +%%% +%%% init_bilingual - starts agent +%%% finish_bilingual +%%% +%%% finish_all +%%% +%%% There is still one problem with these testsuites. If one test +%%% fails, it may not be possible to run some other cases, as it +%%% may have e.g. created some row or loaded some table, that it +%%% didn't undo (since it failed). +%%%----------------------------------------------------------------- + +init_all(Config0) when list(Config0) -> + ?LOG("init_all -> entry with" + "~n Config0: ~p",[Config0]), + + %% -- + %% Fix config: + %% + + DataDir0 = ?config(data_dir, Config0), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + Config1 = lists:keydelete(data_dir, 1, Config0), + Config = [{data_dir, DataDir3 ++ "/"}|Config1], + + %% -- + %% Start nodes + %% + + ?line {ok, SaNode} = start_node(snmp_sa), + ?line {ok, MgrNode} = start_node(snmp_mgr), + + + %% -- + %% Create necessary files + %% + + Dir = ?config(priv_dir, Config), + ?DBG("init_all -> Dir ~p", [Dir]), + + DataDir = ?config(data_dir, Config), + ?DBG("init_all -> DataDir ~p", [DataDir]), + + file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")), + ?DBG("init_all -> MgrDir ~p", [MgrDir]), + + file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")), + ?DBG("init_all -> AgentDir ~p", [AgentDir]), + + file:make_dir(SaDir = filename:join(Dir, "sa_dir/")), + ?DBG("init_all -> SaDir ~p", [SaDir]), + + + %% -- + %% Start and initiate mnesia + %% + + ?DBG("init_all -> load application mnesia", []), + ?line ok = application:load(mnesia), + + ?DBG("init_all -> load application mnesia on node ~p", [SaNode]), + ?line ok = rpc:call(SaNode, application, load, [mnesia]), + + ?DBG("init_all -> application mnesia: set_env dir",[]), + ?line application_controller:set_env(mnesia, dir, + filename:join(Dir, "Mnesia1")), + + ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]), + ?line rpc:call(SaNode, application_controller, set_env, + [mnesia, dir, filename:join(Dir, "Mnesia2")]), + + ?DBG("init_all -> create mnesia schema",[]), + ?line ok = mnesia:create_schema([SaNode, node()]), + + ?DBG("init_all -> start application mnesia",[]), + ?line ok = application:start(mnesia), + + ?DBG("init_all -> start application mnesia on ~p",[SaNode]), + ?line ok = rpc:call(SaNode, application, start, [mnesia]), + Ip = ?LOCALHOST(), + [{snmp_sa, SaNode}, + {snmp_mgr, MgrNode}, + {agent_dir, AgentDir ++ "/"}, + {mgr_dir, MgrDir ++ "/"}, + {sa_dir, SaDir ++ "/"}, + {mib_dir, DataDir}, + {ip, Ip} | + Config]. + +finish_all(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + stop_node(SaNode), + stop_node(MgrNode), + application:stop(mnesia). + +start_v1_agent(Config) when list(Config) -> + start_agent(Config, [v1]). + +start_v1_agent(Config,Opts) when list(Config), list(Opts) -> + start_agent(Config, [v1], Opts). + +start_v2_agent(Config) when list(Config) -> + start_agent(Config, [v2]). + +start_v3_agent(Config) when list(Config) -> + start_agent(Config, [v3]). + +start_bilingual_agent(Config) when list(Config) -> + start_agent(Config, [v1,v2]). + +start_multi_threaded_agent(Config) when list(Config) -> + start_agent(Config, [v2], [{snmp_multi_threaded, true}]). + +stop_agent(Config) when list(Config) -> + ?LOG("stop_agent -> entry with" + "~n Config: ~p",[Config]), + + {Sup, Par} = ?config(snmp_sup, Config), + ?DBG("stop_agent -> attempt to stop (sup) ~p" + "~n Sup: ~p" + "~n Par: ~p", + [Sup, + (catch process_info(Sup)), + (catch process_info(Par))]), + stop_sup(Sup, Par), + + {Sup2, Par2} = ?config(snmp_sub, Config), + ?DBG("stop_agent -> attempt to stop (sub) ~p" + "~n Sup2: ~p" + "~n Par2: ~p", + [Sup2, + (catch process_info(Sup2)), + (catch process_info(Par2))]), + stop_sup(Sup2, Par2), + + ?DBG("stop_agent -> done - now cleanup config", []), + C1 = lists:keydelete(snmp_sup, 1, Config), + lists:keydelete(snmp_sub, 1, C1). + + +stop_sup(Pid, _) when node(Pid) == node() -> + case (catch process_info(Pid)) of + PI when list(PI) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + exit(Pid, kill), + await_stopped(Pid, Ref); + {'EXIT', _Reason} -> + ?LOG("stop_sup -> ~p not running", [Pid]), + ok + end; +stop_sup(Pid, _) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + ?LOG("stop_sup -> Ref: ~p", [Ref]), + %% Pid ! {'EXIT', Parent, shutdown}, % usch + exit(Pid, kill), + await_stopped(Pid, Ref). + +await_stopped(Pid, Ref) -> + receive + {'DOWN', Ref, process, Pid, _Reason} -> + ?DBG("received down message for ~p", [Pid]), + ok + after 10000 -> + ?INF("await_stopped -> timeout for ~p",[Pid]), + erlang:demonitor(Ref), + ?FAIL({failed_stop,Pid}) + end. + + +start_agent(Config, Vsn) -> + start_agent(Config, Vsn, []). +start_agent(Config, Vsn, Opts) -> + ?LOG("start_agent -> entry (~p) with" + "~n Config: ~p" + "~n Vsn: ~p" + "~n Opts: ~p",[node(), Config, Vsn, Opts]), + + ?line AgentDir = ?config(agent_dir, Config), + ?line SaNode = ?config(snmp_sa, Config), + + snmp_app_env_init(vsn_init(Vsn) ++ + [{audit_trail_log, read_write_log}, + {audit_trail_log_dir, AgentDir}, + {audit_trail_log_size, {10240, 10}}, + {force_config_reload, false}, + {snmp_agent_type, master}, + {snmp_config_dir, AgentDir}, + {snmp_db_dir, AgentDir}, + {snmp_local_db_auto_repair, true}, + {snmp_master_agent_verbosity, trace}, + {snmp_supervisor_verbosity, trace}, + {snmp_mibserver_verbosity, trace}, + {snmp_symbolic_store_verbosity, trace}, + {snmp_note_store_verbosity, trace}, + {snmp_net_if_verbosity, trace}], + Opts), + + + process_flag(trap_exit,true), + + {ok, AppSup} = snmp_app_sup:start_link(), + unlink(AppSup), + ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]), + + ?DBG("start_agent -> start master agent (old style)",[]), + Sup = case (catch snmpa_app:start(normal)) of + {ok, S} -> + ?DBG("start_agent -> started, Sup: ~p",[S]), + S; + + Else -> + ?DBG("start_agent -> unknown result: ~n~p",[Else]), + %% Get info about the apps we depend on + MnesiaInfo = mnesia_running(), + ?FAIL({start_failed,Else,MnesiaInfo}) + end, + + ?DBG("start_agent -> unlink from supervisor",[]), + ?line unlink(Sup), + ?line SaDir = ?config(sa_dir, Config), + ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]), + ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]), + ?DBG("start_agent -> done",[]), + ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config]. + + +vsn_init(Vsn) -> + vsn_init([v1,v2,v3], Vsn, []). + +vsn_init([], _Vsn, Acc) -> + Acc; +vsn_init([V|Vsns], Vsn, Acc) -> + case lists:member(V, Vsn) of + true -> + vsn_init(Vsns, Vsn, [{V, true}|Acc]); + false -> + vsn_init(Vsns, Vsn, [{V, false}|Acc]) + end. + +snmp_app_env_init(Env0, Opts) -> + ?DBG("snmp_app_env_init -> unload snmp",[]), + ?line application:unload(snmp), + ?DBG("snmp_app_env_init -> load snmp",[]), + ?line application:load(snmp), + ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]), + F1 = fun({Key,Val} = New, Acc0) -> + ?DBG("snmp_app_env_init -> " + "updating setting ~p to ~p", [Key, Val]), + case lists:keyreplace(Key, 1, Acc0, New) of + Acc0 -> + [New|Acc0]; + Acc -> + Acc + end + end, + Env = lists:foldr(F1, Env0, Opts), + ?DBG("snmp_app_env_init -> Env: ~p",[Env]), + F2 = fun({Key,Val}) -> + ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]), + application_controller:set_env(snmp, Key, Val) + end, + lists:foreach(F2, Env). + + + + +%% Test if application is running +mnesia_running() -> ?IS_MNESIA_RUNNING(). +crypto_running() -> ?IS_CRYPTO_RUNNING(). + + +start_sub(Dir) -> + ?DBG("start_sub -> entry",[]), + Opts = [{db_dir, Dir}, + {supervisor, [{verbosity, trace}]}], + %% BMK BMK +% {ok, P} = snmp_supervisor:start_sub(Dir), + {ok, P} = snmpa_supervisor:start_sub_sup(Opts), + unlink(P), + {ok, {P, self()}}. + +create_tables(SaNode) -> + ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables}, + {attributes, [a1,a2]}]). + +delete_tables() -> + mnesia:delete_table(friendsTable2), + mnesia:delete_table(kompissTable2), + mnesia:delete_table(snmp_variables). + +%% Creation is done in runtime! +delete_mib_storage_mnesia_tables() -> + mnesia:delete_table(snmpa_mib_data), + mnesia:delete_table(snmpa_mib_tree), + mnesia:delete_table(snmpa_symbolic_store). + +%%----------------------------------------------------------------- +%% A test case is always one of: +%% - v1 specific case +%% - v2 specific case +%% - v1 and v2 case +%% All v1 specific cases are prefixed with v1_, and all v2 with +%% v2_. E.g. v1_trap/v2_trap. +%% +%% All other cases are shared. However, the testserver uses the name +%% of the case to generate a file for that case. The same case cannot +%% be used in different configurations in the same suite. Therefore +%% all these functions exists in two variants, the base function +%% <base>, and a second version <base>_2. There may be several +%% versions as well, <base>_N. +%%----------------------------------------------------------------- +mib_storage(suite) -> [ + mib_storage_ets, + mib_storage_dets, + mib_storage_mnesia, + mib_storage_size_check_ets, + mib_storage_size_check_dets, + mib_storage_size_check_mnesia, + mib_storage_varm_dets, + mib_storage_varm_mnesia + ]. + +mib_storage_ets(suite) -> {req, [], {conf, init_mib_storage_ets, + mib_storage_ets_cases(), + finish_mib_storage_ets}}. + +mib_storage_dets(suite) -> {req, [], {conf, init_mib_storage_dets, + mib_storage_dets_cases(), + finish_mib_storage_dets}}. + +mib_storage_mnesia(suite) -> {req, [], {conf, init_mib_storage_mnesia, + mib_storage_mnesia_cases(), + finish_mib_storage_mnesia}}. + +mib_storage_size_check_ets(suite) -> + {req, [], {conf, + init_size_check_mse, + mse_size_check_cases(), + finish_size_check_mse}}. + +mib_storage_size_check_dets(suite) -> + {req, [], {conf, + init_size_check_msd, + msd_size_check_cases(), + finish_size_check_msd}}. + +mib_storage_size_check_mnesia(suite) -> + {req, [], {conf, + init_size_check_msm, + msm_size_check_cases(), + finish_size_check_msm}}. + +mib_storage_varm_dets(suite) -> + {req, [], {conf, + init_varm_mib_storage_dets, + varm_mib_storage_dets_cases(), + finish_varm_mib_storage_dets}}. + +mib_storage_varm_mnesia(suite) -> + {req, [], {conf, + init_varm_mib_storage_mnesia, + varm_mib_storage_mnesia_cases(), + finish_varm_mib_storage_mnesia}}. + +mib_storage_ets_cases() -> + [ + mse_simple, + mse_v1_processing, + mse_big, + mse_big2, + mse_loop_mib, + mse_api, + mse_sa_register, + mse_v1_trap, + mse_sa_error, + mse_next_across_sa, + mse_undo, + mse_standard_mib, + mse_community_mib, + mse_framework_mib, + mse_target_mib, + mse_notification_mib, + mse_view_based_acm_mib, + mse_sparse_table, + mse_me_of, + mse_mib_of]. + +mib_storage_dets_cases() -> + [ + msd_simple, + msd_v1_processing, + msd_big, + msd_big2, + msd_loop_mib, + msd_api, + msd_sa_register, + msd_v1_trap, + msd_sa_error, + msd_next_across_sa, + msd_undo, + msd_standard_mib, + msd_community_mib, + msd_framework_mib, + msd_target_mib, + msd_notification_mib, + msd_view_based_acm_mib, + msd_sparse_table, + msd_me_of, + msd_mib_of + ]. + +mib_storage_mnesia_cases() -> + [ + msm_simple, + msm_v1_processing, + msm_big, + msm_big2, + msm_loop_mib, + msm_api, + msm_sa_register, + msm_v1_trap, + msm_sa_error, + msm_next_across_sa, + msm_undo, + msm_standard_mib, + msm_community_mib, + msm_framework_mib, + msm_target_mib, + msm_notification_mib, + msm_view_based_acm_mib, + msm_sparse_table, + msm_me_of, + msm_mib_of + ]. + +mse_size_check_cases() -> + [mse_size_check]. + +msd_size_check_cases() -> + [msd_size_check]. + +msm_size_check_cases() -> + [msm_size_check]. + +varm_mib_storage_dets_cases() -> + [msd_varm_mib_start]. + +varm_mib_storage_mnesia_cases() -> + [msm_varm_mib_start]. + +init_mib_storage_ets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,ets}, + init_ms(Config, [MibStorage]). + +init_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + init_ms(Config, [MibStorage]). + +init_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + init_ms(Config, [MibStorage]). + +init_ms(Config, Opts) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts], + [{vsn, v1} | start_v1_agent(Config,Opts1)]. + +init_size_check_mse(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, ets}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msd(Config) when list(Config) -> + AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage, {dets, AgentDir}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msm(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, {mnesia,[]}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_ms(Config, Opts) when list(Config) -> + SaNode = ?GCONF(snmp_sa, Config), + %% We are using v3 here, so crypto must be supported or else... + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + create_tables(SaNode), + AgentDir = ?GCONF(agent_dir, Config), + MgrDir = ?GCONF(mgr_dir, Config), + Ip = ?GCONF(ip, Config), + ?line ok = + config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_agent(Config, [v3], Opts)]. + +init_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_dets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +init_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_mnesia -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +finish_mib_storage_ets(Config) when list(Config) -> + ?LOG("finish_mib_storage_ets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_mib_storage_dets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_dets -> entry", []), + delete_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_size_check_mse(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msd(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msm(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_ms(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + + +%% These are just interface functions to fool the test server +mse_simple(X) -> simple(X). +mse_v1_processing(X) -> v1_processing(X). +mse_big(X) -> big(X). +mse_big2(X) -> big2(X). +mse_loop_mib(X) -> loop_mib(X). +mse_api(X) -> api(X). +mse_sa_register(X) -> sa_register(X). +mse_v1_trap(X) -> v1_trap(X). +mse_sa_error(X) -> sa_error(X). +mse_next_across_sa(X) -> next_across_sa(X). +mse_undo(X) -> undo(X). +mse_standard_mib(X) -> snmp_standard_mib(X). +mse_community_mib(X) -> snmp_community_mib(X). +mse_framework_mib(X) -> snmp_framework_mib(X). +mse_target_mib(X) -> snmp_target_mib(X). +mse_notification_mib(X) -> snmp_notification_mib(X). +mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +mse_sparse_table(X) -> sparse_table(X). +mse_me_of(X) -> ms_me_of(X). +mse_mib_of(X) -> ms_mib_of(X). + +msd_simple(X) -> simple(X). +msd_v1_processing(X) -> v1_processing(X). +msd_big(X) -> big(X). +msd_big2(X) -> big2(X). +msd_loop_mib(X) -> loop_mib(X). +msd_api(X) -> api(X). +msd_sa_register(X) -> sa_register(X). +msd_v1_trap(X) -> v1_trap(X). +msd_sa_error(X) -> sa_error(X). +msd_next_across_sa(X) -> next_across_sa(X). +msd_undo(X) -> undo(X). +msd_standard_mib(X) -> snmp_standard_mib(X). +msd_community_mib(X) -> snmp_community_mib(X). +msd_framework_mib(X) -> snmp_framework_mib(X). +msd_target_mib(X) -> snmp_target_mib(X). +msd_notification_mib(X) -> snmp_notification_mib(X). +msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msd_sparse_table(X) -> sparse_table(X). +msd_me_of(X) -> ms_me_of(X). +msd_mib_of(X) -> ms_mib_of(X). + +msm_simple(X) -> simple(X). +msm_v1_processing(X) -> v1_processing(X). +msm_big(X) -> big(X). +msm_big2(X) -> big2(X). +msm_loop_mib(X) -> loop_mib(X). +msm_api(X) -> api(X). +msm_sa_register(X) -> sa_register(X). +msm_v1_trap(X) -> v1_trap(X). +msm_sa_error(X) -> sa_error(X). +msm_next_across_sa(X) -> next_across_sa(X). +msm_undo(X) -> undo(X). +msm_standard_mib(X) -> snmp_standard_mib(X). +msm_community_mib(X) -> snmp_community_mib(X). +msm_framework_mib(X) -> snmp_framework_mib(X). +msm_target_mib(X) -> snmp_target_mib(X). +msm_notification_mib(X) -> snmp_notification_mib(X). +msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msm_sparse_table(X) -> sparse_table(X). +msm_me_of(X) -> ms_me_of(X). +msm_mib_of(X) -> ms_mib_of(X). + + +mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X). +msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X). +msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X). + +msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X). +msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X). + +ms_size_check(suite) -> []; +ms_size_check(Config) when list(Config) -> + p("ms_size_check..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?LOG("mib server size check...", []), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMPv2-MIB"), + ?line load_master_std("SNMPv2-TM"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMPv2-MIB"), + ?line unload_master("SNMPv2-TM"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + + +varm_mib_start(suite) -> []; +varm_mib_start(Config) when list(Config) -> + p("varm_mib_start..."), + ?LOG("varm_mib_start -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + %% Start the agent + Opts = ?GCONF(agent_opts, Config), + Config1 = start_v1_agent(Config, Opts), + + %% Sleep some in order for the agent to start properly + ?DBG("varm_mib_start -> sleep some (before loading mobs)", []), + ?SLEEP(5000), + + %% Load all the mibs + HardwiredMibs = loaded_mibs(), + ?DBG("varm_mib_start -> load all mibs", []), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + + %% Unload the hardwired mibs + ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []), + ?SLEEP(1000), + ?DBG("varm_mib_start -> unload (hardwired) mibs", []), + ?line unload_mibs(HardwiredMibs), %% unload hardwired + + ?DBG("varm_mib_start -> sleep some (before stopping agent)", []), + ?SLEEP(1000), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + Config2 = stop_agent(Config1), + + %% Sleep some in order for the agent to stop properly + ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []), + ?SLEEP(5000), + + %% Start the agent (again) + ?DBG("varm_mib_start -> start the agent", []), + Config3 = start_v1_agent(Config2, Opts), + + ?DBG("varm_mib_start -> sleep some (before starting tests)", []), + ?SLEEP(5000), + + %% Perform the test(s) + ?DBG("varm_mib_start -> perform the tests", []), + try_test(snmp_community_mib), + try_test(snmp_framework_mib), + try_test(snmp_target_mib), + try_test(snmp_notification_mib), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + stop_agent(Config3), + ok. + + +-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]). +-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]). +-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +ms_me_of(suite) -> []; +ms_me_of(Config) when list(Config) -> + p("ms_me_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = me_of(?snmpTrapCommunity_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = me_of(?vacmViewSpinLock_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +me_of(Oid) -> + case snmpa:me_of(Oid) of + {ok, #me{oid = Oid}} -> + ok; + {ok, #me{oid = OtherOid}} -> + case lists:reverse(Oid) of + [0|Rest] -> + case lists:reverse(Rest) of + OtherOid -> + ok; + AnotherOid -> + {error, {invalid_oid, Oid, AnotherOid}} + end; + _ -> + {error, {invalid_oid, Oid, OtherOid}} + end; + {error, Reason} -> + {error, Reason}; + Else -> + {error, Else} + end. + + +ms_mib_of(suite) -> []; +ms_mib_of(Config) when list(Config) -> + p("ms_mib_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance, + 'SNMP-USER-BASED-SM-MIB'), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +mib_of(Oid, ExpectedMibName) -> + ?DBG("mib_of -> entry with" + "~n Oid: ~p" + "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]), + %% case snmpa:mib_of(Oid) of + MibOf = snmpa:mib_of(Oid), + ?DBG("mib_of -> MibOf: ~n~p", [MibOf]), + case MibOf of + {ok, ExpectedMibName} -> + ok; + {ok, OtherMibName} -> + {error, {invalid_mib, ExpectedMibName, OtherMibName}}; + {error, Reason} -> + {error, Reason}; + Else -> + ?DBG("mib_of -> Else: ~n~p", [Else]), + {error, Else} + end. + + +app_info(suite) -> []; +app_info(Config) when list(Config) -> + SnmpDir = app_dir(snmp), + SslDir = app_dir(ssl), + CryptoDir = app_dir(crypto), + Attr = snmp:module_info(attributes), + AppVsn = + case lists:keysearch(app_vsn, 1, Attr) of + {value, {app_vsn, V}} -> + V; + false -> + "undefined" + end, + io:format("Root dir: ~s~n" + "SNMP: Application dir: ~s~n" + " Application ver: ~s~n" + "SSL: Application dir: ~s~n" + "CRYPTO: Application dir: ~s~n", + [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]), + ok. + +app_dir(App) -> + case code:lib_dir(App) of + D when list(D) -> + filename:basename(D); + {error, _Reason} -> + "undefined" + end. + + +test_v1(suite) -> {req, [], {conf, init_v1, v1_cases(), finish_v1}}. + +%v1_cases() -> [loop_mib]; +v1_cases() -> + [simple, + db_notify_client, + v1_processing, big, big2, loop_mib, + api, subagent, mnesia, multiple_reqs, + sa_register, v1_trap, sa_error, next_across_sa, undo, reported_bugs, + standard_mibs, sparse_table, cnt_64, + opaque, + % opaque]. + + change_target_addr_config]. + +init_v1(Config) when list(Config) -> + ?line SaNode = ?config(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v1} | start_v1_agent(Config)]. + +finish_v1(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v2(suite) -> {req, [], {conf, init_v2, v2_cases(), finish_v2}}. + +%v2_cases() -> [loop_mib_2]; +v2_cases() -> + [simple_2, v2_processing, big_2, big2_2, loop_mib_2, + api_2, subagent_2, mnesia_2, + multiple_reqs_2, sa_register_2, v2_trap, v2_inform, sa_error_2, + next_across_sa_2, undo_2, reported_bugs_2, standard_mibs_2, + v2_types, implied, sparse_table_2, cnt_64_2, opaque_2, v2_caps]. + +init_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_v2_agent(Config)]. + +finish_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v1_v2(suite) -> {req, [], {conf, init_v1_v2, v1_v2_cases(), finish_v1_v2}}. + +v1_v2_cases() -> + [simple_bi]. + +init_v1_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, bilingual} | start_bilingual_agent(Config)]. + +finish_v1_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v3(suite) -> {req, [], {conf, init_v3, v3_cases(), finish_v3}}. + +%v3_cases() -> [loop_mib_3]; +v3_cases() -> + [simple_3, v3_processing, + big_3, big2_3, api_3, subagent_3, mnesia_3, loop_mib_3, + multiple_reqs_3, sa_register_3, v3_trap, v3_inform, sa_error_3, + next_across_sa_3, undo_3, reported_bugs_3, standard_mibs_3, + v3_security, + v2_types_3, implied_3, sparse_table_3, cnt_64_3, opaque_3, v2_caps_3]. + +init_v3(Config) when list(Config) -> + %% Make sure crypto works, otherwise start_agent will fail + %% and we will be stuck with a bunch of mnesia tables for + %% the rest of this suite... + ?DBG("start_agent -> start crypto app",[]), + case os:type() of + vxworks -> + no_crypto; + _ -> + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end + end, + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v3], MgrDir, AgentDir, + tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_v3_agent(Config)]. + +finish_v3(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_multi_threaded(suite) -> {req, [], {conf, init_mt, mt_cases(), finish_mt}}. + +mt_cases() -> + [multi_threaded, mt_trap]. + +init_mt(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_multi_threaded_agent(Config)]. + +finish_mt(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +%% This one *must* be run first in each case. +init_case(Config) when list(Config) -> + ?DBG("init_case -> entry with" + "~n Config: ~p", [Config]), + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + MasterNode = node(), + + SaHost = ?HOSTNAME(SaNode), + MgrHost = ?HOSTNAME(MgrNode), + MasterHost = ?HOSTNAME(MasterNode), + {ok, MasterIP} = snmp_misc:ip(MasterHost), + {ok, MIP} = snmp_misc:ip(MgrHost), + {ok, SIP} = snmp_misc:ip(SaHost), + + + put(mgr_node, MgrNode), + put(sa_node, SaNode), + put(master_node, MasterNode), + put(sa_host, SaHost), + put(mgr_host, MgrHost), + put(master_host, MasterHost), + put(mip, tuple_to_list(MIP)), + put(masterip , tuple_to_list(MasterIP)), + put(sip, tuple_to_list(SIP)), + + MibDir = ?config(mib_dir, Config), + put(mib_dir, MibDir), + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + put(std_mib_dir, StdM), + + MgrDir = ?config(mgr_dir, Config), + put(mgr_dir, MgrDir), + + put(vsn, ?config(vsn, Config)), + ?DBG("init_case -> exit with" + "~n MasterNode: ~p" + "~n SaNode: ~p" + "~n MgrNode: ~p" + "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]), + {SaNode, MgrNode, MibDir}. + +load_master(Mib) -> + ?DBG("load_master -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]). + +load_master_std(Mib) -> + ?DBG("load_master_std -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]). + +unload_master(Mib) -> + ?DBG("unload_master -> entry with" + "~n Mib: ~p", [Mib]), + ok = snmpa:unload_mibs(snmp_master_agent, [Mib]). + +loaded_mibs() -> + ?DBG("loaded_mibs -> entry",[]), + Info = snmpa:info(snmp_master_agent), + {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info), + [atom_to_list(Mib) || {Mib,_,_} <- Mibs]. + +unload_mibs(Mibs) -> + ?DBG("unload_mibs -> entry with" + "~n Mibs: ~p", [Mibs]), + ok = snmpa:unload_mibs(snmp_master_agent, Mibs). + +start_subagent(SaNode, RegTree, Mib) -> + ?DBG("start_subagent -> entry with" + "~n SaNode: ~p" + "~n RegTree: ~p" + "~n Mib: ~p", [SaNode, RegTree, Mib]), + MA = whereis(snmp_master_agent), + ?DBG("start_subagent -> MA: ~p", [MA]), + MibDir = get(mib_dir), + Mib1 = join(MibDir,Mib), + %% BMK BMK +% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of + case rpc:call(SaNode, snmpa_supervisor, + start_sub_agent, [MA, RegTree, [Mib1]]) of + {ok, SA} -> + ?DBG("start_subagent -> SA: ~p", [SA]), + {ok, SA}; + Error -> + ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]}) + end. + +stop_subagent(SA) -> + ?DBG("stop_subagent -> entry with" + "~n SA: ~p", [SA]), + %% BNK BMK + %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]). + rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]). + +%%----------------------------------------------------------------- +%% This function takes care of the old OTP-SNMPEA-MIB. +%% Unfortunately, the testcases were written to use the data in the +%% internal tables, and these table are now obsolete and not used +%% by the agent. Therefore, we emulate them by using +%% OLD-SNMPEA-MIB, which uses the default impl. of all tables. +%% +%% These two rows must exist in intCommunityTable +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. +%% (But with the manager's IP address) +%% +%%----------------------------------------------------------------- +init_old() -> + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [6 | "public"], + {get(mip), "public", 2, 2}), + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [13 | "standard trap"], + {get(mip), "standard trap", 2, 1}), + snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]). + + + +simple(suite) -> []; +simple(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(simple_standard_test). + +simple_2(X) -> simple(X). + +simple_bi(suite) -> []; +simple_bi(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(vsn, v1), % First, try v1 manager + try_test(simple_standard_test), + + put(vsn, v2), % Then, try v2 manager + try_test(simple_standard_test). + +simple_3(X) -> + simple(X). + +big(suite) -> []; +big(Config) when list(Config) -> + ?DBG("big -> entry", []), + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?DBG("big -> SA: ~p", [SA]), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB"). + +big_2(X) -> big(X). + +big_3(X) -> big(X). + + +big2(suite) -> []; +big2(Config) when list(Config) -> + %% This is exactly the same tests as 'big', but with the + %% v2 equivalent of the mibs. + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"), + ?line load_master("OLD-SNMPEA-MIB-v2"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB-v2"). + +big2_2(X) -> big2(X). + +big2_3(X) -> big2(X). + + +multi_threaded(suite) -> []; +multi_threaded(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(multi_threaded_test), + ?line unload_master("Test1"). + +mt_trap(suite) -> []; +mt_trap(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + ?line load_master("TestTrapv2"), + try_test(mt_trap_test, [MA]), + ?line unload_master("TestTrapv2"), + ?line unload_master("Test1"). + +v2_types(suite) -> []; +v2_types(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(types_v2_test), + ?line unload_master("Test1"). + +v2_types_3(X) -> v2_types(X). + + +implied(suite) -> []; +implied(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(implied_test,[MA]), + ?line unload_master("Test1"). + +implied_3(X) -> implied(X). + + +sparse_table(suite) -> []; +sparse_table(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(sparse_table_test), + ?line unload_master("Test1"). + +sparse_table_2(X) -> sparse_table(X). + +sparse_table_3(X) -> sparse_table(X). + +cnt_64(suite) -> []; +cnt_64(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(cnt_64_test, [MA]), + ?line unload_master("Test1"). + +cnt_64_2(X) -> cnt_64(X). + +cnt_64_3(X) -> cnt_64(X). + +opaque(suite) -> []; +opaque(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(opaque_test), + ?line unload_master("Test1"). + +opaque_2(X) -> opaque(X). + +opaque_3(X) -> opaque(X). + + +change_target_addr_config(suite) -> []; +change_target_addr_config(Config) when list(Config) -> + p("Testing changing target address config..."), + ?LOG("change_target_addr_config -> entry",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(sname,snmp_suite), + put(verbosity,trace), + + MA = whereis(snmp_master_agent), + + ?LOG("change_target_addr_config -> load TestTrap",[]), + ?line load_master("TestTrap"), + + ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,trace), + + %% First send some traps that will arive att the original manager + ?LOG("change_target_addr_config -> send trap",[]), + try_test(ma_trap1, [MA]), + + ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,silence), + + %% Start new dummy listener + ?LOG("change_target_addr_config -> start dummy manager",[]), + ?line {ok,Pid,NewPort} = dummy_manager_start(MA), + + %% Reconfigure + ?LOG("change_target_addr_config -> reconfigure",[]), + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_addr_conf(AgentDir, NewPort), + ?line snmp_target_mib:reconfigure(AgentDir), + + %% Send the trap again + ?LOG("change_target_addr_config -> send trap again",[]), + catch dummy_manager_send_trap2(Pid), + + ?LOG("change_target_addr_config -> await trap ack",[]), + catch dummy_manager_await_trap2_ack(), + + ?LOG("change_target_addr_config -> stop dummy manager",[]), + ?line ok = dummy_manager_stop(Pid), + + ?LOG("change_target_addr_config -> reset target address config",[]), + ?line reset_target_addr_conf(AgentDir), + + ?LOG("change_target_addr_config -> unload TestTrap",[]), + ?line unload_master("TestTrap"). + + +dummy_manager_start(MA) -> + ?DBG("dummy_manager_start -> entry",[]), + Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]), + ?DBG("dummy_manager_start -> Pid: ~p",[Pid]), + await_dummy_manager_started(Pid). + +await_dummy_manager_started(Pid) -> + receive + {dummy_manager_started,Pid,Port} -> + ?DBG("dummy_manager_start -> acknowledge received with" + "~n Port: ~p",[Port]), + {ok,Pid,Port}; + {'EXIT', Pid, Reason} -> + {error, Pid, Reason}; + O -> + ?LOG("dummy_manager_start -> received unknown message:" + "~n ~p",[O]), + await_dummy_manager_started(Pid) + end. + +dummy_manager_stop(Pid) -> + ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]), + Pid ! stop, + receive + {dummy_manager_stopping, Pid} -> + ?DBG("dummy_manager_stop -> acknowledge received",[]), + ok + after 10000 -> + ?ERR("dummy_manager_stop -> timeout",[]), + timeout + end. + +dummy_manager_send_trap2(Pid) -> + ?DBG("dummy_manager_send_trap2 -> entry",[]), + Pid ! {send_trap,testTrap2}. + +dummy_manager_await_trap2_ack() -> + ?DBG("dummy_manager_await_trap2 -> entry",[]), + receive + {received_trap,Trap} -> + ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]), + %% Note: + %% Without this sleep the v2_inform_i testcase failes! There + %% is no relation between these two test cases as far as I + %% able to figure out... + sleep(60000), + ok; + O -> + ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]), + ok + after 10000 -> + ?ERR("dummy_manager_await_trap2 -> timeout",[]), + timeout + end. + +dummy_manager_init(Parent,MA) -> + ?DBG("dummy_manager_init -> entry with" + "~n Parent: ~p" + "~n MA: ~p",[Parent,MA]), + {ok,S} = gen_udp:open(0,[{recbuf,65535}]), + ?DBG("dummy_manager_init -> S: ~p",[S]), + {ok,Port} = inet:port(S), + ?DBG("dummy_manager_init -> Port: ~p",[Port]), + Parent ! {dummy_manager_started,self(),Port}, + dummy_manager_loop(Parent,S,MA). + +dummy_manager_loop(P,S,MA) -> + ?LOG("dummy_manager_loop -> ready for receive",[]), + receive + {send_trap,Trap} -> + ?LOG("dummy_manager_loop -> received trap send request" + "~n Trap: ~p",[Trap]), + snmpa:send_trap(MA, Trap, "standard trap"), + dummy_manager_loop(P,S,MA); + {udp, _UdpId, Ip, UdpPort, Bytes} -> + ?LOG("dummy_manager_loop -> received upd message" + "~n from: ~p:~p" + "~n size: ~p", + [Ip, UdpPort, dummy_manager_message_sz(Bytes)]), + R = dummy_manager_handle_message(Bytes), + ?DBG("dummy_manager_loop -> R: ~p",[R]), + P ! R, + dummy_manager_loop(P,S,MA); + stop -> + ?DBG("dummy_manager_loop -> received stop request",[]), + P ! {dummy_manager_stopping, self()}, + gen_udp:close(S), + exit(normal); + O -> + ?LOG("dummy_manager_loop -> received unknown message:" + "~n ~p",[O]), + dummy_manager_loop(P,S,MA) + end. + +dummy_manager_message_sz(B) when binary(B) -> + size(B); +dummy_manager_message_sz(L) when list(L) -> + length(L); +dummy_manager_message_sz(_) -> + undefined. + +dummy_manager_handle_message(Bytes) -> + case (catch snmp_pdus:dec_message(Bytes)) of + {'EXIT',Reason} -> + ?ERR("dummy_manager_handle_message -> " + "failed decoding message only:~n ~p",[Reason]), + {error,Reason}; + M -> + ?DBG("dummy_manager_handle_message -> decoded message:" + "~n ~p",[M]), + {received_trap,M} + end. + + +api(suite) -> []; +api(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(api_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +api_2(X) -> api(X). + +api_3(X) -> api(X). + + +subagent(suite) -> []; +subagent(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + try_test(load_test_sa), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + + p("Loading previous subagent mib in master and testing..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]), + try_test(load_test), + + p("Unloading previous subagent mib in master and testing..."), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]), + try_test(unreg_test), + p("Testing register subagent..."), + rpc:call(SaNode, snmp, register_subagent, + [MA, ?klas1, SA]), + try_test(load_test_sa), + + ?line stop_subagent(SA), + try_test(unreg_test). + +subagent_2(X) -> subagent(X). + +subagent_3(X) -> subagent(X). + + +mnesia(suite) -> []; +mnesia(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent with mnesia impl..."), + {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + try_test(big_test_2), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA). + +mnesia_2(X) -> mnesia(X). + +mnesia_3(X) -> mnesia(X). + + +multiple_reqs(suite) -> + {req, [], {conf, init_mul, mul_cases(), finish_mul}}. + +mul_cases() -> + [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err]. + +multiple_reqs_2(suite) -> + {req, [], {conf, init_mul, mul_cases_2(), finish_mul}}. + +multiple_reqs_3(_X) -> + {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}. + + +mul_cases_2() -> + [mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2, mul_set_err_2]. + + +mul_cases_3() -> + [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3]. + + +init_mul(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + [{mul_sub, SA} | Config]. + +finish_mul(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + SA = ?config(mul_sub, Config), + + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA), + lists:keydelete(mul_sub, 1, Config). + +mul_get(suite) -> []; +mul_get(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get..."), + try_test(do_mul_get). + +mul_get_2(X) -> mul_get(X). + +mul_get_3(X) -> mul_get(X). + + +mul_get_err(suite) -> []; +mul_get_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get with error..."), + try_test(do_mul_get_err). + +mul_get_err_2(X) -> mul_get_err(X). + +mul_get_err_3(X) -> mul_get_err(X). + + +mul_next(suite) -> []; +mul_next(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next). + +mul_next_2(X) -> mul_next(X). + +mul_next_3(X) -> mul_next(X). + + +mul_next_err(suite) -> []; +mul_next_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next_err). + +mul_next_err_2(X) -> mul_next_err(X). + +mul_next_err_3(X) -> mul_next_err(X). + + +mul_set(suite) -> []; +mul_set(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set..."), + try_test(do_mul_set). + +mul_set_2(X) -> mul_set(X). + +mul_set_3(X) -> mul_set(X). + + +mul_set_err(suite) -> []; +mul_set_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set with error..."), + try_test(do_mul_set_err). + +mul_set_err_2(X) -> mul_set_err(X). + +mul_set_err_3(X) -> mul_set_err(X). + + +sa_register(suite) -> []; +sa_register(Config) when list(Config) -> + ?DBG("sa_register -> entry", []), + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?DBG("sa_register -> start subagent", []), + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + + ?DBG("sa_register -> unregister subagent", []), + p("Testing unregister subagent (2)..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Loading SA-MIB..."), + ?DBG("sa_register -> unload mibs", []), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + ?DBG("sa_register -> unload mibs", []), + snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]), + ?DBG("sa_register -> register subagent", []), + rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]), + try_test(sa_mib), + + ?DBG("sa_register -> stop subagent", []), + ?line stop_subagent(SA). + +sa_register_2(X) -> sa_register(X). + +sa_register_3(X) -> sa_register(X). + + +v1_trap(suite) -> []; +v1_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_trap1, [MA]), + try_test(ma_trap2, [MA]), + try_test(ma_v2_2_v1_trap, [MA]), + try_test(ma_v2_2_v1_trap2, [MA]), + + p("Testing trap sending from subagent..."), + try_test(sa_trap1, [SA]), + try_test(sa_trap2, [SA]), + try_test(sa_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v2_trap(suite) -> []; +v2_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + + try_test(ma_v2_trap1, [MA]), + try_test(ma_v2_trap2, [MA]), + try_test(ma_v1_2_v2_trap, [MA]), + try_test(ma_v1_2_v2_trap2, [MA]), + + try_test(sa_mib), + p("Testing trap sending from subagent..."), + try_test(sa_v1_2_v2_trap1, [SA]), + try_test(sa_v1_2_v2_trap2, [SA]), + try_test(sa_v1_2_v2_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v3_trap(X) -> + v2_trap(X). + +v2_inform(suite) -> + {req, [], {conf, init_v2_inform, [v2_inform_i], finish_v2_inform}}. + +v3_inform(_X) -> + %% v2_inform(X). + {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}. + +init_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +init_v3_inform(X) -> + init_v2_inform(X). + +finish_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +finish_v3_inform(X) -> + finish_v2_inform(X). + + + +v2_inform_i(suite) -> []; +v2_inform_i(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing inform sending from master agent... NOTE! This test\ntakes a " + "few minutes (5) to complete."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_v2_inform1, [MA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"). + +v3_inform_i(X) -> v2_inform_i(X). + + +sa_error(suite) -> []; +sa_error(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing sa bad value (is_set_ok)..."), + try_test(sa_errs_bad_value), + + p("Testing sa gen err (set)..."), + try_test(sa_errs_gen_err), + + p("Testing too big..."), + try_test(sa_too_big), + + ?line unload_master("OLD-SNMPEA-MIB"), + stop_subagent(SA). + +sa_error_2(X) -> sa_error(X). + +sa_error_3(X) -> sa_error(X). + + +next_across_sa(suite) -> []; +next_across_sa(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Loading another subagent mib..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]), + + rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]), + try_test(load_test_sa), + + p("Testing next across subagent (endOfMibView from SA)..."), + try_test(next_across_sa), + + p("Unloading mib"), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Starting another subagent"), + ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"), + p("Testing next across subagent (wrong prefix from SA)..."), + try_test(next_across_sa), + + stop_subagent(SA), + stop_subagent(SA2). + +next_across_sa_2(X) -> next_across_sa(X). + +next_across_sa_3(X) -> next_across_sa(X). + + +undo(suite) -> []; +undo(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing undo phase at master agent..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]), + try_test(undo_test), + try_test(api_test2), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]), + + p("Testing bad return values from instrum. funcs..."), + try_test(bad_return), + + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]), + + p("Testing undo phase at subagent..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]), + ?line ok = snmpa:register_subagent(MA, ?klas3, SA), + ?line ok = snmpa:register_subagent(MA, ?klas4, SA), + try_test(undo_test), + try_test(api_test3), + + p("Testing undo phase across master/subagents..."), + try_test(undo_test), + try_test(api_test3), + stop_subagent(SA). + +undo_2(X) -> undo(X). + +undo_3(X) -> undo(X). + +%% Req. Test2 +v1_processing(suite) -> []; +v1_processing(Config) when list(Config) -> + ?DBG("v1_processing -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v1_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v2_processing(suite) -> []; +v2_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v3_processing(suite) -> []; +v3_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), % same as v2! + ?line unload_master("Test2"). + + +%% We'll try get/set/trap and inform for all the auth & priv protocols. +%% For informs, the mgr is auth-engine. The agent has to sync. This is +%% accomplished by the first inform sent. That one will generate a +%% report, which makes it in sync. The notification-generating +%% application times out, and send again. This time it'll work. +v3_security(suite) -> [v3_crypto_basic, v3_md5_auth, v3_sha_auth, v3_des_priv]. + +v3_crypto_basic(suite) -> []; +v3_crypto_basic(_Config) -> + EID = [0,0,0,0,0,0,0,0,0,0,0,2], + %% From rfc2274 appendix A.3.1 + ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID), + ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f, + 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] = + KMd5_1, + %% From rfc2274 appendix A.3.2 + ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID), + ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23, + 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] = + KSHA_1, + %% From rfc2274, appendix A.5.1 + ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9, + 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] = + snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + %% From rfc2274, appendix A.5.2 + ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4, + 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db, + 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + KSHA_1t = lists:sublist(KSHA_1, 16), + KSHA_2t = lists:sublist(KSHA_2, 16), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b, + 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + + %% Try with correct random + ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2), + ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1), + ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2), + ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2), + ok. + + + +v3_md5_auth(suite) -> []; +v3_md5_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing MD5 authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authMD5"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_sha_auth(suite) -> []; +v3_sha_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing SHA authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authSHA"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_des_priv(suite) -> []; +v3_des_priv(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing DES encryption...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +%% Make sure mgr is in sync with agent +v3_sync(Funcs) -> + ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]), + g([[sysDescr, 0]]), + expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]), + g([[sysDescr, 0]]), + expect(433, [{[sysDescr,0], any}]), + lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs). + +v3_inform_sync(MA) -> + ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, + "standard inform", []), + %% Make sure agent is in sync with mgr... + ?DBG("v3_sync -> wait some time: ",[]), + sleep(20000), % more than 1500*10 in target_addr.conf + ?DBG("v3_sync -> await response",[]), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]). + + +v2_caps(suite) -> []; +v2_caps(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(v2_caps_i, [node()]). + +v2_caps_3(X) -> v2_caps(X). + + +v2_caps_i(Node) -> + ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]), + g([[sysORID, Idx], [sysORDescr, Idx]]), + ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]}, + {[sysORDescr, Idx], "test cap"}]), + ?line rpc:call(Node, snmp, del_agent_caps, [Idx]), + g([[sysORID, Idx]]), + ?line expect(2, [{[sysORID, Idx], noSuchInstance}]). + + +%% Req. Test2 +v1_proc() -> + ?DBG("v1_proc -> entry", []), + %% According to RFC1157. + %% Template: <Section>:<list no> + v1_get_p(), + v1_get_next_p(), + v1_set_p(). + + +v1_get_p() -> + %% 4.1.2:1 + g([[test2]]), + ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]), + g([[tDescr]]), + ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]), + g([[tDescr2,0]]), + ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]), + g([[tDescr3,0]]), + ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]), + g([[tDescr4,0]]), + ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'}, + {[tDescr,0], 'NULL'}]), + g([[sysDescr,3]]), + ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]), + + %% 4.1.2:2 + g([[tTable]]), + ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]), + g([[tEntry]]), + ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]), + + %% 4.1.2:3 + g([[tTooBig, 0]]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.2:4 + g([[tGenErr1, 0]]), + ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]). + + +v1_get_next_p() -> + %% 4.1.3:1 + gn([[1,3,7,1]]), + ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]), + gn([[tDescr2]]), + ?line expect(11, tooBig, 0, any), + + %% 4.1.3:2 + gn([[tTooBig]]), + io:format("We currently don't handle tooBig correct!!!\n"), +% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]), + ?line expect(20, tooBig, 0, any), + + %% 4.1.3:3 + gn([[tGenErr1]]), +% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]), + ?line expect(40, genErr, 1, any), + gn([[tGenErr2]]), +% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]), + ?line expect(41, genErr, 1, any), + gn([[sysDescr], [tGenErr3]]), +% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'}, +% {[tGenErr3], 'NULL'}]). + ?line expect(42, genErr, 2, any). + +v1_set_p() -> + %% 4.1.5:1 + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]), + s([{[tDescr3], s, "noSuchObject"}]), + ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]), + s([{[tDescr3,1], s, "noSuchInstance"}]), + ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]), + s([{[tDescr2,0], s, "inconsistentName"}]), + ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]), + + %% 4.1.5:2 + s([{[tDescr2, 0], i, 4}]), + ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.1.5:3 + %% The standard is quite incorrect here. The resp pdu was too big. In + %% the resp pdu, we have the original vbs. In the tooBig pdu we still + %% have to original vbs => the tooBig pdu is too big as well!!! It + %% may not get it to the manager, unless the agent uses 'NULL' instead + %% of the std-like original value. + s([{[tTooBig, 0], s, ?tooBigStr}]), + %% according to std: +% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.5:4 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]), + s([{[tDescr2, 0], s, "commit_fail"}]), + ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]). + +%% Req. Test2 +v2_proc() -> + %% According to RFC1905. + %% Template: <Section>:<list no> + ?DBG("v2_proc -> entry",[]), + v2_get_p(), + v2_get_next_p(), + v2_get_bulk_p(), + v2_set_p(). + +v2_get_p() -> + %% 4.2.1:2 + ?DBG("v2_get_p -> entry",[]), + g([[test2]]), + ?line expect(10, [{[test2], noSuchObject}]), + g([[tDescr]]), + ?line expect(11, [{[tDescr], noSuchObject}]), + g([[tDescr4,0]]), + ?line expect(12, [{[tDescr4,0], noSuchObject}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}, + {[tDescr,0], noSuchObject}]), + g([[tTable]]), + ?line expect(14, [{[tTable], noSuchObject}]), + g([[tEntry]]), + ?line expect(15, [{[tEntry], noSuchObject}]), + + %% 4.2.1:3 + g([[tDescr2,0]]), %% instrum ret noSuchName!!! + ?line expect(20, [{[tDescr2,0], noSuchInstance}]), + g([[tDescr3,0]]), + ?line expect(21, [{[tDescr3,0], noSuchInstance}]), + g([[sysDescr,3]]), + ?line expect(22, [{[sysDescr, 3], noSuchInstance}]), + g([[tIndex,1]]), + ?line expect(23, [{[tIndex, 1], noSuchInstance}]), + + %% 4.2.1 - any other error: genErr + g([[tGenErr1, 0]]), + ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]), + + %% 4.2.1 - tooBig + g([[tTooBig, 0]]), + ?line expect(40, tooBig, 0, []). + + +v2_get_next_p() -> + %% 4.2.2:2 + ?DBG("v2_get_next_p -> entry",[]), + gn([[1,3,7,1]]), + ?line expect(10, [{[1,3,7,1], endOfMibView}]), + gn([[sysDescr], [1,3,7,1]]), + ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gn([[tCnt2, 1]]), + ?line expect(12, [{[tCnt2,2], 100}]), + gn([[tCnt2, 2]]), + ?line expect(12, [{[tCnt2,2], endOfMibView}]), + + %% 4.2.2 - any other error: genErr + gn([[tGenErr1]]), + ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]), + gn([[tGenErr2]]), + ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]), + gn([[sysDescr], [tGenErr3]]), + ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'}, + {[tGenErr3], 'NULL'}]), + + %% 4.2.2 - tooBig + gn([[tTooBig]]), + ?line expect(20, tooBig, 0, []). + +v2_get_bulk_p() -> + %% 4.2.3 + ?DBG("v2_get_bulk_p -> entry",[]), + gb(1, 1, []), + ?line expect(10, []), + gb(-1, 1, []), + ?line expect(11, []), + gb(-1, -1, []), + ?line expect(12, []), + gb(-1, -1, []), + ?line expect(13, []), + gb(2, 0, [[sysDescr], [1,3,7,1]]), + ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(1, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(0, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]), + ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]), + ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[sysDescr, 0], "Erlang SNMP agent"}]), + + gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig. + ?line expect(19, []), + + gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]), + ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'}, + {[sysObjectID], 'NULL'}, + {[tGenErr1], 'NULL'}, + {[sysDescr], 'NULL'}]), + gb(0, 2, [[tCnt2, 1]]), + ?line expect(21, [{[tCnt2,2], 100}, + {[tCnt2,2], endOfMibView}]). + + +v2_set_p() -> + %% 4.2.5:1 + ?DBG("v2_set_p -> entry",[]), + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]), + + %% 4.2.5:2 + s([{[1,3,6,1,0], s, "noSuchObject"}]), + ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]), + + %% 4.2.5:3 + s([{[tDescr2, 0], i, 4}]), + ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.2.5:4 + s([{[tStr, 0], s, ""}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]), + s([{[tStr, 0], s, "12345"}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]), + + %% 4.2.5:5 - N/A + + %% 4.2.5:6 + s([{[tInt1, 0], i, 0}]), + ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]), + s([{[tInt1, 0], i, 5}]), + ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]), + s([{[tInt2, 0], i, 0}]), + ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]), + s([{[tInt2, 0], i, 5}]), + ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]), + s([{[tInt3, 0], i, 5}]), + ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]), + + %% 4.2.5:7 + s([{[tDescrX, 1, 1], s, "noCreation"}]), + ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]), + + %% 4.2.5:8 + s([{[tDescrX, 1, 2], s, "inconsistentName"}]), + ?line expect(80, inconsistentName, 1, + [{[tDescrX, 1, 2], "inconsistentName"}]), + + %% 4.2.5:9 + s([{[tCnt, 1, 2], i, 5}]), + ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]), + + %% 4.2.5:10 + s([{[tDescr2,0], s, "inconsistentValue"}]), + ?line expect(100, inconsistentValue, 1, + [{[tDescr2,0], "inconsistentValue"}]), + + %% 4.2.5:11 + s([{[tDescr2,0], s, "resourceUnavailable"}]), + ?line expect(110, resourceUnavailable, 1, + [{[tDescr2,0],"resourceUnavailable"}]), + + %% 4.2.5:12 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]). + + %% commitFailed and undoFailed is tested by the 'undo' case. + + +%% Req. OLD-SNMPEA-MIB +table_test() -> + io:format("Testing simple get, next and set on communityTable...~n"), +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. + Key1c3 = [intCommunityViewIndex,get(mip),is("public")], + Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")], + Key1c4 = [intCommunityAccess,get(mip),is("public")], + EndKey = [intCommunityEntry,[9],get(mip),is("public")], + gn([[intCommunityEntry]]), + ?line expect(7, [{Key1c3, 2}]), + gn([[intCommunityTable]]), + ?line expect(71, [{Key1c3, 2}]), + gn([[community]]), + ?line expect(72, [{Key1c3, 2}]), + gn([[otpSnmpeaMIB]]), + ?line expect(73, [{Key1c3, 2}]), + gn([[ericsson]]), + ?line expect(74, [{Key1c3, 2}]), + gn([Key1c3]), + ?line expect(8, [{Key2c3, 2}]), + gn([Key2c3]), + ?line expect(9, [{Key1c4, 2}]), + gn([EndKey]), + AgentIp = [intAgentIpAddress,0], + ?line expect(10, [{AgentIp, any}]), + g([Key1c3]), + ?line expect(11, [{Key1c3, 2}]), + g([EndKey]), + ?line ?v1_2(expect(12, noSuchName, 1, any), + expect(12, [{EndKey, noSuchObject}])), + + io:format("Testing row creation/deletion on communityTable...~n"), + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + s([{NewKeyc5, ?createAndGo}]), + ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any), + s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]), + ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]), + g([NewKeyc4]), + ?line expect(16, [{NewKeyc4, 2}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(17, [{NewKeyc5, ?destroy}]), + s([{NewKeyc4, 2}]), + ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]), + s([{NewKeyc5, ?createAndWait}]), + ?line expect(19, [{NewKeyc5, ?createAndWait}]), + g([NewKeyc5]), + ?line expect(20, [{NewKeyc5, ?notReady}]), + s([{NewKeyc4, 2}]), + ?line expect(21, [{NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(22, [{NewKeyc5, ?notReady}]), + s([{NewKeyc3, 2}]), + ?line expect(23, [{NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(24, [{NewKeyc5, ?notInService}]), + s([{NewKeyc5, ?active}]), + ?line expect(25, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(26, [{NewKeyc5, ?destroy}]), + s([{NewKeyc3, 3}]), + ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]), + otp_1128(). + +%% Req. system group +simple_standard_test() -> + ?DBG("simple_standard_test -> entry",[]), + gn([[1,1]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3]]), + ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6]]), + ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1]]), + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2]]), + ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1]]), + ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1,1]]), + ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[sysDescr]]), + ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr,0]]), + ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr]]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{[sysDescr], noSuchObject}])), + g([[1,6,7,0]]), + ?line ?v1_2(expect(41, noSuchName, 1, any), + expect(3, [{[1,6,7,0], noSuchObject}])), + gn([[1,13]]), + ?line ?v1_2(expect(4, noSuchName,1, any), + expect(4, [{[1,13], endOfMibView}])), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + g([[sysLocation, 0]]), + ?line expect(6, [{[sysLocation, 0], "new_value"}]), + io:format("Testing noSuchName and badValue...~n"), + s([{[sysServices,0], 3}]), + ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any), + s([{[sysLocation, 0], i, 3}]), + ?line expect(62, ?v1_2(badValue, wrongType), 1, any), + ?DBG("simple_standard_test -> done",[]), + ok. + +%% This is run in the agent node +db_notify_client(suite) -> []; +db_notify_client(Config) when list(Config) -> + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p", + [SaNode,MgrNode,MibDir]), + snmpa_local_db:register_notify_client(self(),?MODULE), + + %% This call (the manager) will issue to set operations, so + %% we expect to receive to notify(insert) calls. + try_test(db_notify_client_test), + + ?DBG("await first notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok + end, + + ?DBG("await second notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok + end, + + snmpa_local_db:unregister_notify_client(self()). + + +%% This is run in the manager node +db_notify_client_test() -> + ?DBG("set first new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + + ?DBG("set second new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]). + +notify(Pid,What) -> + ?DBG("notify(~p,~p) -> called",[Pid,What]), + Pid ! {db_notify_test_reply,What}. + + +%% Req: system group, OLD-SNMPEA-MIB, Klas1 +big_test() -> + ?DBG("big_test -> testing simple next/get/set @ master agent...",[]), + simple_standard_test(), + + ?DBG("big_test -> testing simple next/get/set @ subagent...",[]), + gn([[klas1]]), + ?line expect(1, [{[fname,0], ""}]), + g([[fname,0]]), + ?line expect(2, [{[fname,0], ""}]), + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[fname,0]]), + ?line expect(4, [{[fname,0], "test set"}]), + + ?DBG("big_test -> " + "testing next from last instance in master to subagent...",[]), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname,0], "test set"}]), + s([{[fname,0], s, ""}]), + ?line expect(52, [{[fname,0], ""}]), + + table_test(), + + ?DBG("big_test -> adding one row in subagent table",[]), + _FTab = [friendsEntry], + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {[friendsEntry, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [friendsEntry, [3, 3]]]), + ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?active}]), + s([{[friendsEntry, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]), + + otp_1131(), + + ?DBG("big_test -> adding two rows in subagent table with special INDEX", + []), + s([{[kompissEntry, [1, 3]], s, "kompis3"}, + {[kompissEntry, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?createAndGo}]), + g([[kompissEntry, [1, 3]], + [kompissEntry, [2, 3]]]), + ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + gn([[kompissEntry, [1]], + [kompissEntry, [2]]]), + ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + s([{[kompissEntry, [1, 2]], s, "kompis3"}, + {[kompissEntry, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?createAndGo}]), + gn([[kompissEntry, [1, 1]], + [kompissEntry, [2, 1]]]), + ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?active}]), + s([{[kompissEntry, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]), + s([{[kompissEntry, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]), + ?DBG("big_test -> done",[]), + ok. + +%% Req. system group, Klas2, OLD-SNMPEA-MIB +big_test_2() -> + p("Testing simple next/get/set @ master agent (2)..."), + simple_standard_test(), + + p("Testing simple next/get/set @ subagent (2)..."), + gn([[klas2]]), + ?line expect(1, [{[fname2,0], ""}]), + g([[fname2,0]]), + ?line expect(2, [{[fname2,0], ""}]), + s([{[fname2,0], s, "test set"}]), + ?line expect(3, [{[fname2,0], "test set"}]), + g([[fname2,0]]), + ?line expect(4, [{[fname2,0], "test set"}]), + + otp_1298(), + + p("Testing next from last object in master to subagent (2)..."), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname2,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname2,0], "test set"}]), + + table_test(), + + p("Adding one row in subagent table (2)"), + _FTab = [friendsEntry2], + s([{[friendsEntry2, [2, 3]], s, "kompis3"}, + {[friendsEntry2, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?createAndGo}]), + g([[friendsEntry2, [2, 3]], + [friendsEntry2, [3, 3]]]), + ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?active}]), + s([{[friendsEntry2, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]), + + p("Adding two rows in subagent table with special INDEX (2)"), + s([{[kompissEntry2, [1, 3]], s, "kompis3"}, + {[kompissEntry2, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?createAndGo}]), + g([[kompissEntry2, [1, 3]], + [kompissEntry2, [2, 3]]]), + ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + gn([[kompissEntry2, [1]], + [kompissEntry2, [2]]]), + ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + s([{[kompissEntry2, [1, 2]], s, "kompis3"}, + {[kompissEntry2, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?createAndGo}]), + gn([[kompissEntry2, [1, 1]], + [kompissEntry2, [2, 1]]]), + ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?active}]), + s([{[kompissEntry2, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]), + s([{[kompissEntry2, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]), + ok. + +%% Req. Test1 +multi_threaded_test() -> + p("Testing multi threaded agent..."), + g([[multiStr,0]]), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(1, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "pelle"}]), + ?line expect(2, [{[sysLocation, 0], "pelle"}]), + Pid ! continue, + ?line expect(3, [{[multiStr,0], "ok"}]), + + s([{[multiStr, 0], s, "block"}]), + Pid2 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(4, [{[sysUpTime,0], any}]), + g([[multiStr,0]]), + Pid3 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(5, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "kalle"}]), + Pid3 ! continue, + ?line expect(6, [{[multiStr,0], "ok"}]), + Pid2 ! continue, + ?line expect(7, [{[multiStr,0], "block"}]), + ?line expect(8, [{[sysLocation,0], "kalle"}]). + +%% Req. Test1, TestTrapv2 +mt_trap_test(MA) -> + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + snmpa:send_trap(MA, mtTrap, "standard trap"), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(2, [{[sysUpTime,0], any}]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + Pid ! continue, + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [2]}, + {[multiStr,0], "ok"}]). + + +get_multi_pid() -> + get_multi_pid(10). +get_multi_pid(0) -> + ?line ?FAIL(no_global_name); +get_multi_pid(N) -> + sleep(1000), + case global:whereis_name(snmp_multi_tester) of + Pid when pid(Pid) -> Pid; + _ -> get_multi_pid(N-1) + end. + +%% Req. Test1 +types_v2_test() -> + p("Testing v2 types..."), + + s([{[bits1,0], 2#10}]), + ?line expect(1, [{[bits1,0], ?str(2#10)}]), + g([[bits1,0]]), + ?line expect(2, [{[bits1,0], ?str(2#101)}]), + + s([{[bits2,0], 2#11000000110}]), + ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]), + g([[bits2,0]]), + ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]), + + g([[bits3,0]]), + ?line expect(50, genErr, 1, any), + + g([[bits4,0]]), + ?line expect(51, genErr, 1, any), + + s([{[bits1,0], s, [2#10]}]), + ?line expect(6, ?v1_2(badValue, wrongValue), 1, any), + + s([{[bits2,0], 2#11001001101010011}]), + ?line expect(7, ?v1_2(badValue, wrongValue), 1, any). + + +%% Req. Test1 +implied_test(MA) -> + ?LOG("implied_test -> start",[]), + p("Testing IMPLIED..."), + + snmpa:verbosity(MA,trace), + snmpa:verbosity(MA,trace), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = "apa", + Idx2 = "qq", + ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]), + ?line expect(1, [{[testStatus, Idx1], ?createAndGo}, + {[testDescr, Idx1], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]), + ?line expect(2, [{[testStatus, Idx2], ?createAndGo}, + {[testDescr, Idx2], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr)",[]), + gn([[testDescr]]), + ?line expect(3, [{[testDescr,Idx1], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr) of row 1",[]), + gn([[testDescr,Idx1]]), + ?line expect(4, [{[testDescr,Idx2], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?destroy}]), + ?line expect(5, [{[testStatus, Idx1], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?destroy}]), + ?line expect(6, [{[testStatus, Idx2], ?destroy}]), + + %% Try the same in other table + Idx3 = [1, "apa"], + Idx4 = [1, "qq"], + ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]), + ?line expect(1, [{[testStatus2, Idx3], ?createAndGo}, + {[testDescr2, Idx3], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]), + ?line expect(2, [{[testStatus2, Idx4], ?createAndGo}, + {[testDescr2, Idx4], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr2)",[]), + gn([[testDescr2]]), + ?line expect(3, [{[testDescr2,Idx3], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr2) of row 1",[]), + gn([[testDescr2,Idx3]]), + ?line expect(4, [{[testDescr2,Idx4], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?destroy}]), + ?line expect(5, [{[testStatus2, Idx3], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?destroy}]), + ?line expect(6, [{[testStatus2, Idx4], ?destroy}]), + + snmpa:verbosity(MA,log), + + ?LOG("implied_test -> done",[]). + + + +%% Req. Test1 +sparse_table_test() -> + p("Testing sparse table..."), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + s([{[sparseStatus, Idx1], i, ?createAndGo}, + {[sparseDescr, Idx1], s, "row 1"}]), + ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo}, + {[sparseDescr, Idx1], "row 1"}]), + s([{[sparseStatus, Idx2], i, ?createAndGo}, + {[sparseDescr, Idx2], s, "row 2"}]), + ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo}, + {[sparseDescr, Idx2], "row 2"}]), + ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2], + [sparseStatus,Idx1], [sparseStatus,Idx2]]), + gb(0,5,[[sparseIndex]])), + ?line expect(3, [{[sparseDescr,Idx1], "row 1"}, + {[sparseDescr,Idx2], "row 2"}, + {[sparseStatus,Idx1], ?active}, + {[sparseStatus,Idx2], ?active}, + {[sparseStr,0], "slut"}]), + % Delete the rows + s([{[sparseStatus, Idx1], i, ?destroy}]), + ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]), + s([{[sparseStatus, Idx2], i, ?destroy}]), + ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]). + + +%% Req. Test1 +cnt_64_test(MA) -> + ?LOG("start cnt64 test (~p)",[MA]), + snmpa:verbosity(MA,trace), + ?LOG("start cnt64 test",[]), + p("Testing Counter64, and at the same time, RowStatus is not last column"), + + ?DBG("get cnt64",[]), + g([[cnt64,0]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(1, noSuchName, 1, any), + expect(1, [{[cnt64,0],18446744073709551615}])), + ?DBG("get-next cnt64",[]), + gn([[cnt64]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]), + expect(2, [{[cnt64,0],18446744073709551615}])), + ?DBG("send cntTrap",[]), + snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"}, + {cnt64, 10}, + {sysLocation, "here"}]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"}, + {[sysLocation,0], "here"}]), + expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [1]}, + {[sysContact,0], "pelle"}, + {[cnt64,0], 10}, + {[sysLocation,0], "here"}])), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + ?DBG("create row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]), + ?DBG("create row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]), + + ?DBG("get-next (cntIndex)",[]), + gn([[cntIndex]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]), + expect(3, [{[cntCnt,Idx1], 0}])), + % Delete the rows + ?DBG("delete row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(4, [{[cntStatus, Idx1], ?destroy}]), + ?DBG("delete row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(5, [{[cntStatus, Idx2], ?destroy}]), + catch snmpa:verbosity(MA,log), + ?DBG("done",[]), + ok. + +%% Req. Test1 +opaque_test() -> + p("Testing Opaque datatype..."), + g([[opaqueObj,0]]), + ?line expect(1, [{[opaqueObj,0], "opaque-data"}]). + +%% Req. OLD-SNMPEA-MIB +api_test(MaNode) -> + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [intAgentIpAddress]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, + oid_to_name, [OID]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [[1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, + int_to_enum, ['RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]), + ?line case snmp:date_and_time() of + List when list(List), length(List) == 8 -> ok; + List when list(List), length(List) == 11 -> ok + end. + +%% Req. Klas3 +api_test2() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]), + g([[fname4,0]]), + ?line expect(2, [{[fname4,0], 1}]). + +api_test3() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]). + + +unreg_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[snmpInPkts, 0], any}]). + +load_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[fname,0], ""}]). + +%% Req. Klas1 +load_test_sa() -> + gn([[?v1_2(sysServices,sysORLastChange), 0]]), + ?line expect(1, [{[fname,0], any}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_get() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0], Key1c4, [fname,0],Key1c3, + [sysName,0]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,0], "test"}]), + g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]), + ?line ?v1_2(expect(2, noSuchName, [1,4], any), + expect(2, [{[1,3,7,1], noSuchObject}, + {Key1c4, 2}, + {[sysDescr,0], "Erlang SNMP agent"}, + {[1,3,7,2], noSuchObject}, + {Key1c3, 2}, + {[sysDescr,0], "Erlang SNMP agent"}])). + +%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3. +do_mul_get_err() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]), + ?line ?v1_2(expect(1, noSuchName, 5, any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,2], noSuchInstance}])), + g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname3,0], noSuchObject}, + {Key1c3, 2}, + {[sysName,1], noSuchInstance}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, {[fname,0], "test set"}, + {Key1c3, 2}, {[sysName,0], "test"}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next_err() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[1,3,6,999], endOfMibView}, + {[fname,0], "test set"}, + {[1,3,90], endOfMibView}, + {Key1c3, 2}, + {[sysName,0], "test"}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set() -> + p("Adding one row in subagent table, and one in master table"), + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [sysLocation,0], + [friendsEntry, [3, 3]]]), + ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"}, + {[sysLocation,0], "new_value"}, + {[friendsEntry, [3, 3]], ?active}]), + g([NewKeyc4]), + ?line expect(3, [{NewKeyc4, 2}]), + s([{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]), + ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + p("Adding one row in subagent table, and one in master table"), + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {NewKeyc3, 2}, + {[sysUpTime,0], 45}, % sysUpTime (readOnly) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any), + g([[friendsEntry, [2, 3]]]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])), + g([NewKeyc4]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB +sa_mib() -> + g([[sa, [2,0]]]), + ?line expect(1, [{[sa, [2,0]], 3}]), + s([{[sa, [1,0]], s, "sa_test"}]), + ?line expect(2, [{[sa, [1,0]], "sa_test"}]). + +ma_trap1(MA) -> + snmpa:send_trap(MA, testTrap2, "standard trap"), + ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]), + snmpa:send_trap(MA, testTrap1, "standard trap"), + ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]). + +ma_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap2(MA) -> + snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1}, + {ifAdminStatus, [1], 1}, + {ifOperStatus, [1], 2}]), + ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}]). + +sa_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]], + "pelle"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}]). + +ma_v2_trap1(MA) -> + ?DBG("ma_v2_traps -> entry with MA = ~p => " + "send standard trap: testTrapv22",[MA]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]), + snmpa:send_trap(MA, testTrapv21, "standard trap"), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmp ++ [1]}]). + +ma_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}]). + +%% Note: This test case takes a while... actually a couple of minutes. +ma_v2_inform1(MA) -> + ?DBG("ma_v2_inform -> entry with MA = ~p => " + "send notification: testTrapv22",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag1, self()}, + "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag1, [_]} -> + ok; + {snmp_targets, tag1, Addrs1} -> + ?line ?FAIL({bad_addrs, Addrs1}) + after + 5000 -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag1, {got_response, _}} -> + ok; + {snmp_notification, tag1, {no_response, _}} -> + ?line ?FAIL(no_response) + after + 20000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + + %% + %% -- The rest is possibly erroneous... + %% + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag2, self()}, + "standard inform", []), + ?line expect(2, {inform, false}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag2, [_]} -> + ok; + {snmp_targets, tag2, Addrs2} -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]), + ?line ?FAIL({bad_addrs, Addrs2}) + after + 5000 -> + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag2, {got_response, _}} -> + ?line ?FAIL(got_response); + {snmp_notification, tag2, {no_response, _}} -> + ok + after + 240000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag2) timeout",[]), + ?line ?FAIL(nothing_at_all) + end. + + +ma_v1_2_v2_trap(MA) -> + snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmpTraps ++ [3]}, + {[ifIndex, 1], 1}, + {[snmpTrapEnterprise, 0], [1,2,3]}]). + + +ma_v1_2_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}, + {[snmpTrapEnterprise, 0], ?system}]). + + +sa_v1_2_v2_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + +sa_v1_2_v2_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], "pelle"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +sa_v1_2_v2_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 2]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_bad_value() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2}, + {[sa, [2,0]], 5}, % badValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, badValue, 2, any), + s([{NewKeyc3, 2}, + {[sa, [2,0]], 6}, % wrongValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, ?v1_2(badValue, wrongValue), 2, any), + g([NewKeyc4]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_gen_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2},{NewKeyc4, 2}, + {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]), + ?line expect(1, genErr, 4, any), +% The row might have been added; we don't know. +% (as a matter of fact we do - it is added, because the agent +% first sets its own vars, and then th SAs. Lets destroy it. + s([{NewKeyc5, ?destroy}]), + ?line expect(2, [{NewKeyc5, ?destroy}]). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_too_big() -> + g([[sa, [4,0]]]), + ?line expect(1, tooBig). + +%% Req. Klas1, system group, snmp group (v1/v2) +next_across_sa() -> + gn([[sysDescr],[klas1,5]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {[snmpInPkts, 0], any}]). + +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2} +%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2} +%% Req. Klas3, Klas4 +undo_test() -> + s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]), + ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any), + s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]), + ?line expect(3, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]), + ?line expect(4, ?v1_2(genErr, commitFailed), 1, any), +% unfortunatly we don't know if we'll get undoFailed or commitFailed. +% it depends on which order the agent traverses the varbind list. +% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]), +% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]), + ?line expect(6, genErr, 2, any). + +%% Req. Klas3, Klas4 +bad_return() -> + g([[fStatus4,4], + [fName4,4]]), + ?line expect(4, genErr, 2, any), + g([[fStatus4,5], + [fName4,5]]), + ?line expect(5, genErr, 1, any), + g([[fStatus4,6], + [fName4,6]]), + ?line expect(6, genErr, 2, any), + gn([[fStatus4,7], + [fName4,7]]), + ?line expect(7, genErr, 2, any), + gn([[fStatus4,8], + [fName4,8]]), + ?line expect(8, genErr, 1, any), + gn([[fStatus4,9], + [fName4,9]]), + ?line expect(9, genErr, 2, any). + + +%%%----------------------------------------------------------------- +%%% Test the implementation of standard mibs. +%%% We should *at least* try to GET all variables, just to make +%%% sure the instrumentation functions work. +%%% Note that many of the functions in the standard mib is +%%% already tested by the normal tests. +%%%----------------------------------------------------------------- +standard_mibs(suite) -> + [snmp_standard_mib, snmp_community_mib, + snmp_framework_mib, + snmp_target_mib, snmp_notification_mib, + snmp_view_based_acm_mib]. + +standard_mibs_2(suite) -> + [snmpv2_mib_2, snmp_community_mib_2, + snmp_framework_mib_2, + snmp_target_mib_2, snmp_notification_mib_2, + snmp_view_based_acm_mib_2]. + +standard_mibs_3(suite) -> + [snmpv2_mib_3,snmp_framework_mib_3, snmp_mpd_mib_3, + snmp_target_mib_3, snmp_notification_mib_3, + snmp_view_based_acm_mib_3, snmp_user_based_sm_mib_3]. + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v1. +%% o Test the counters and control objects in SNMP-STANDARD-MIB +%%----------------------------------------------------------------- +snmp_standard_mib(suite) -> []; +snmp_standard_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?DBG("snmp_standard_mib -> std_mib_init", []), + try_test(std_mib_init), + + ?DBG("snmp_standard_mib -> std_mib_a", []), + InBadVsns = try_test(std_mib_a), + put(vsn, v2), + ?DBG("snmp_standard_mib -> std_mib_read", []), + try_test(std_mib_read), + put(vsn, v1), + + ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]), + Bad = try_test(std_mib_b, [InBadVsns]), + ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []), + try_test(std_mib_read, [], [{community, "bad community"}]), + ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []), + try_test(std_mib_write, [], [{community, "public"}]), + ?DBG("snmp_standard_mib -> std_mib_asn_err", []), + try_test(std_mib_asn_err), + ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]), + try_test(std_mib_c, [Bad]), + ?DBG("snmp_standard_mib -> std_mib_a", []), + try_test(standard_mib_a), + + ?DBG("snmp_standard_mib -> std_mib_finish", []), + try_test(std_mib_finish), + ?DBG("snmp_standard_mib -> std_mib_test_finish", []), + try_test(standard_mib_test_finish, [], [{community, "bad community"}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_a() -> + ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]), + ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]), + ?line OutPkts2 = OutPkts + 1, + %% There are some more counters we could test here, but it's not that + %% important, since they are removed from SNMPv2-MIB. + ok. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_init() -> + %% disable authentication failure traps. (otherwise w'd get many of + %% them - this is also a test to see that it works). + s([{[snmpEnableAuthenTraps,0], 2}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_finish() -> + %% enable again + s([{[snmpEnableAuthenTraps,0], 1}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_test_finish() -> + %% force a authenticationFailure + std_mib_write(), + %% check that we got a trap + ?line expect(2, trap, [1,2,3], 4, 0, []). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_read() -> + ?DBG("std_mib_read -> entry", []), + g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply + ?DBG("std_mib_read -> await timeout (i.e. no reply)", []), + ?line expect(1, timeout). % make sure we don't get a trap! + + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_write() -> + ?DBG("std_mib_write -> entry", []), + s([{[sysLocation, 0], "new_value"}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_asn_err() -> + snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]). + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v2 and v3. +%% o Test the counters and control objects in SNMPv2-MIB +%%----------------------------------------------------------------- +snmpv2_mib_2(suite) -> []; +snmpv2_mib_2(Config) when list(Config) -> + ?LOG("snmpv2_mib_2 -> start",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?DBG("snmpv2_mib_2 -> standard mib init",[]), + try_test(std_mib_init), + + ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]), + InBadVsns = try_test(std_mib_a), + + ?DBG("snmpv2_mib_2 -> make a bad version read",[]), + put(vsn, v1), + try_test(std_mib_read), + + ?DBG("snmpv2_mib_2 -> bad version read",[]), + put(vsn, v2), + Bad = try_test(std_mib_b, [InBadVsns]), + + ?DBG("snmpv2_mib_2 -> read with bad community",[]), + try_test(std_mib_read, [], [{community, "bad community"}]), + + ?DBG("snmpv2_mib_2 -> write with public community",[]), + try_test(std_mib_write, [], [{community, "public"}]), + + ?DBG("snmpv2_mib_2 -> asn err",[]), + try_test(std_mib_asn_err), + + ?DBG("snmpv2_mib_2 -> check counters",[]), + try_test(std_mib_c, [Bad]), + + ?DBG("snmpv2_mib_2 -> get som counters",[]), + try_test(snmpv2_mib_a), + + ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]), + try_test(std_mib_finish), + + ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, " + "then disable auth traps",[]), + try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]), + + ?LOG("snmpv2_mib_2 -> done",[]). + +%% Req. SNMPv2-MIB +snmpv2_mib_3(suite) -> []; +snmpv2_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + InBadVsns = try_test(std_mib_a), + put(vsn, v1), + try_test(std_mib_read), + put(vsn, v3), + _Bad = try_test(std_mib_b, [InBadVsns]), + try_test(snmpv2_mib_a), + + try_test(std_mib_finish). + +-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]). + +%% Req. SNMPv2-MIB +snmpv2_mib_test_finish() -> + %% force a authenticationFailure + ?DBG("ma_v2_inform -> write to std mib",[]), + std_mib_write(), + + %% check that we got a trap + ?DBG("ma_v2_inform -> await trap",[]), + ?line expect(2, v2trap, [{[sysUpTime,0], any}, + {[snmpTrapOID,0], ?authenticationFailure}]), + + %% and the the inform + ?DBG("ma_v2_inform -> await inform",[]), + ?line expect(2, {inform,true}, [{[sysUpTime,0], any}, + {[snmpTrapOID,0],?authenticationFailure}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_a() -> + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + + ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]), + InBadVsns. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_b(InBadVsns) -> + ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]), + ?line InBadVsns2 = InBadVsns + 1, + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] = + get_req(4, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + {InBadCommunityNames, InBadCommunityUses, InASNErrs}. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) -> + ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] = + get_req(1, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + ?line InBadCommunityNames2 = InBadCommunityNames + 1, + ?line InBadCommunityUses2 = InBadCommunityUses + 1, + ?line InASNErrs2 = InASNErrs + 1. + +%% Req. SNMPv2-MIB +snmpv2_mib_a() -> + ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]), + s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]), + ?line expect(3, [{[snmpSetSerialNo,0], SetSerial}, + {[sysLocation, 0], "val2"}]), + s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]), + ?line expect(4, inconsistentValue, 2, + [{[sysLocation, 0], "val3"}, + {[snmpSetSerialNo,0], SetSerial}]), + ?line ["val2"] = get_req(5, [[sysLocation,0]]). + + +%%----------------------------------------------------------------- +%% o Bad community uses/name is tested already +%% in SNMPv2-MIB and STANDARD-MIB. +%% o Test add/deletion of rows. +%%----------------------------------------------------------------- +snmp_community_mib(suite) -> []; +snmp_community_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + try_test(snmp_community_mib), + ?line unload_master("SNMP-COMMUNITY-MIB"). + +snmp_community_mib_2(X) -> snmp_community_mib(X). + +%% Req. SNMP-COMMUNITY-MIB +snmp_community_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o Test engine boots / time +%%----------------------------------------------------------------- +snmp_framework_mib(suite) -> []; +snmp_framework_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + try_test(snmp_framework_mib), + ?line unload_master("SNMP-FRAMEWORK-MIB"). + +snmp_framework_mib_2(X) -> snmp_framework_mib(X). + +snmp_framework_mib_3(suite) -> []; +snmp_framework_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(snmp_framework_mib). + + +%% Req. SNMP-FRAMEWORK-MIB +snmp_framework_mib() -> + ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]), + ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]), + sleep(5000), + ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]), + if + EngineTime+7 < EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + EngineTime+4 > EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + true -> ok + end, + ?line case get_req(4, [[snmpEngineBoots,0]]) of + [Boots] when integer(Boots) -> ok; + Else -> ?FAIL(Else) + end, + ok. + +%%----------------------------------------------------------------- +%% o Test the counters +%%----------------------------------------------------------------- +snmp_mpd_mib_3(suite) -> []; +snmp_mpd_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + UnknownPDUHs = try_test(snmp_mpd_mib_a), + try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]), + try_test(snmp_mpd_mib_c, [UnknownPDUHs]). + + +%% Req. SNMP-MPD-MIB +snmp_mpd_mib_a() -> + ?line [UnknownSecs, InvalidMsgs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0]]), + Pdu = #pdu{type = 'get-request', + request_id = 23, + error_status = noError, + error_index = 0, + varbinds = []}, + SPdu = #scopedPdu{contextEngineID = "agentEngine", + contextName = "", + data = Pdu}, + ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu), + V3Hdr1 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [7], + msgSecurityModel = 23, % bad sec model + msgSecurityParameters = []}, + V3Hdr2 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [6], % bad flag combination + msgSecurityModel = 3, + msgSecurityParameters = []}, + Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1, + data = SPDUBytes}, + Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2, + data = SPDUBytes}, + ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1), + ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2), + snmp_test_mgr:send_bytes(MsgBytes1), + snmp_test_mgr:send_bytes(MsgBytes2), + + ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0], + [snmpUnknownPDUHandlers, 0]]), + ?line UnknownSecs2 = UnknownSecs + 1, + ?line InvalidMsgs2 = InvalidMsgs + 1, + UnknownPDUHs. + +-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]). +snmp_mpd_mib_b() -> + g([[sysUpTime,0]]), + ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]). + + +snmp_mpd_mib_c(UnknownPDUHs) -> + ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]), + ?line UnknownPDUHs2 = UnknownPDUHs + 1. + + +snmp_target_mib(suite) -> []; +snmp_target_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-TARGET-MIB"), + try_test(snmp_target_mib), + ?line unload_master("SNMP-TARGET-MIB"). + +snmp_target_mib_2(X) -> snmp_target_mib(X). + +snmp_target_mib_3(X) -> snmp_target_mib(X). + +snmp_target_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +snmp_notification_mib(suite) -> []; +snmp_notification_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + try_test(snmp_notification_mib), + ?line unload_master("SNMP-NOTIFICATION-MIB"). + +snmp_notification_mib_2(X) -> snmp_notification_mib(X). + +snmp_notification_mib_3(X) -> snmp_notification_mib(X). + +snmp_notification_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o add/delete views and try them +%% o try boundaries +%%----------------------------------------------------------------- +snmp_view_based_acm_mib(suite) -> []; +snmp_view_based_acm_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master("Test2"), + snmp_view_based_acm_mib(), + ?line unload_master("Test2"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib() -> + snmpa:verbosity(net_if,trace), + snmpa:verbosity(master_agent,trace), + ?LOG("start snmp_view_based_acm_mib test",[]), + %% The user "no-rights" is present in USM, and is mapped to security + %% name 'no-rights", which is not present in VACM. + %% So, we'll add rights for it, try them and delete them. + %% We'll give "no-rights" write access to tDescr.0 and read access + %% to tDescr2.0 + %% These are the options we'll use to the mgr + Opts = [{user, "no-rights"}, {community, "no-rights"}], + %% Find the valid secmodel, and one invalid secmodel. + {SecMod, InvSecMod} = + case get(vsn) of + v1 -> {?SEC_V1, ?SEC_V2C}; + v2 -> {?SEC_V2C, ?SEC_USM}; + v3 -> {?SEC_USM, ?SEC_V1} + end, + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Now, add a mapping from "no-rights" -> "no-rights-group" + GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]], + GRow1 = + [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"}, + {GRow1Status, ?createAndGo}], + ?DBG("set '~p'",[GRow1]), + ?line try_test(do_set, [GRow1]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Create a mapping for another sec model, and make sure it dosn't + %% give us access + GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]], + GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"}, + {GRow2Status, ?createAndGo}], + + ?DBG("set '~p'",[GRow2]), + ?line try_test(do_set, [GRow2]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [GRow2Status]), + + RVName = "rv_name", + WVName = "wv_name", + + %% Access row + ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1], + ARow1Status = [vacmAccessStatus, ARow1Idx], + ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1}, + {[vacmAccessReadViewName, ARow1Idx], RVName}, + {[vacmAccessWriteViewName, ARow1Idx], WVName}, + {ARow1Status, ?createAndGo}], + + %% This access row would give acces, if InvSecMod was valid. + ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1], + ARow2Status = [vacmAccessStatus, ARow2Idx], + ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1}, + {[vacmAccessReadViewName, ARow2Idx], "internet"}, + {[vacmAccessWriteViewName, ARow2Idx], "internet"}, + {ARow2Status, ?createAndGo}], + + ?line try_test(do_set, [ARow2]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [ARow2Status]), + + + %% Add valid row + ?line try_test(do_set, [ARow1]), + + ?line try_test(use_no_rights, [], Opts), + + %% Create the view family + VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access + VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access + VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access + VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access + VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx], + VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx], + VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx], + VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx], + + ?line try_test(add_row, [VRow1Status]), + ?line try_test(add_row, [VRow2Status]), + ?line try_test(add_row, [VRow3Status]), + + %% We're supposed to have access now... + ?line try_test(use_rights, [], Opts), + + %% Change Row3 to Row4 + ?line try_test(del_row, [VRow3Status]), + ?line try_test(add_row, [VRow4Status]), + + %% We should still have access... + ?line try_test(use_rights, [], Opts), + + %% Delete rows + ?line try_test(del_row, [GRow1Status]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete rest of rows + ?line try_test(del_row, [ARow1Status]), + ?line try_test(del_row, [VRow1Status]), + ?line try_test(del_row, [VRow2Status]), + ?line try_test(del_row, [VRow4Status]), + + ?line try_test(use_no_rights, [], Opts), + snmpa:verbosity(master_agent,log). + +do_set(Row) -> + s(Row), + expect(1, Row). + +add_row(RowStatus) -> + s([{RowStatus, ?createAndGo}]), + expect(1, [{RowStatus, ?createAndGo}]). + +del_row(RowStatus) -> + s([{RowStatus, ?destroy}]), + expect(1, [{RowStatus, ?destroy}]). + + + +use_no_rights() -> + g([[xDescr,0]]), + ?v1_2_3(expect(11, noSuchName, 1, any), + expect(12, [{[xDescr,0], noSuchObject}]), + expect(13, authorizationError, 1, any)), + g([[xDescr2,0]]), + ?v1_2_3(expect(21, noSuchName, 1, any), + expect(22, [{[xDescr2,0], noSuchObject}]), + expect(23, authorizationError, 1, any)), + gn([[xDescr]]), + ?v1_2_3(expect(31, noSuchName, 1, any), + expect(32, [{[xDescr], endOfMibView}]), + expect(33, authorizationError, 1, any)), + s([{[xDescr,0], "tryit"}]), + ?v1_2_3(expect(41, noSuchName, 1, any), + expect(42, noAccess, 1, any), + expect(43, authorizationError, 1, any)). + + +use_rights() -> + g([[xDescr,0]]), + expect(1, [{[xDescr,0], any}]), + g([[xDescr2,0]]), + expect(2, [{[xDescr2,0], any}]), + s([{[xDescr,0], "tryit"}]), + expect(3, noError, 0, any), + g([[xDescr,0]]), + expect(4, [{[xDescr,0], "tryit"}]). + +mk_ln(X) -> + [length(X) | X]. + +%%----------------------------------------------------------------- +%% o add/delete users and try them +%% o test all secLevels +%% o test all combinations of protocols +%% o try bad ops; check counters +%%----------------------------------------------------------------- +snmp_user_based_sm_mib_3(suite) -> []; +snmp_user_based_sm_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + _AgentDir = ?config(agent_dir, Config), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + + %% The newUser used here already has VACM access. + + %% Add a new user in the simplest way; just createAndGo + try_test(v3_sync, [[{usm_add_user1, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new user + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"), + DesKey1 = lists:sublist(ShaKey1, 16), + + %% Change the new user's keys - 1 + try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + MgrDir = ?config(mgr_dir, Config), + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"), + DesKey2 = lists:sublist(ShaKey2, 16), + + %% Change the new user's keys - 2 + ?line try_test(v3_sync, + [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + reset_usm_mgr(MgrDir), + ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2), + ?line load_master("Test2"), + ?line try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Change the new user's keys - 3 + ?line try_test(v3_sync, + [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new keys + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Try some read requests + ?line try_test(v3_sync, [[{usm_read, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Delete the new user + ?line try_test(v3_sync, [[{usm_del_user, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try some bad requests + ?line try_test(v3_sync, [[{usm_bad, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("SNMP-USER-BASED-SM-MIB"). + +-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]). + +usm_add_user1() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +usm_use_user() -> + v2_proc(). + + +%% Change own public keys +usm_key_change1(ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_shaxxxxxxxxxx", + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_desxxxxxx", + DesKey), + Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change own private keys +usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change other's public keys +usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}], + s(Vbs1), + ?line expect(1, noAccess, 1, any), + Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs2), + ?line expect(2, noAccess, 1, any), + + + Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs3), + ?line expect(1, Vbs3). + +usm_read() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ?line g([[usmUserSecurityName, NewRowIndex], + [usmUserCloneFrom, NewRowIndex], + [usmUserAuthKeyChange, NewRowIndex], + [usmUserOwnAuthKeyChange, NewRowIndex], + [usmUserPrivKeyChange, NewRowIndex], + [usmUserOwnPrivKeyChange, NewRowIndex]]), + ?line expect(1, + [{[usmUserSecurityName, NewRowIndex], "newUser"}, + {[usmUserCloneFrom, NewRowIndex], [0,0]}, + {[usmUserAuthKeyChange, NewRowIndex], ""}, + {[usmUserOwnAuthKeyChange, NewRowIndex], ""}, + {[usmUserPrivKeyChange, NewRowIndex], ""}, + {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]), + ok. + + + +usm_del_user() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]). + +-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]). + +-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]). + +-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]). + +-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]). + +-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]). + +usm_bad() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, inconsistentName, 1, any), + + RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs2), + ?line expect(2, wrongValue, 1, any), + + RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs3), + ?line expect(3, Vbs3), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]), + ?line expect(4, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]), + ?line expect(5, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]), + ?line expect(6, wrongValue, 1, any), + ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]), + ?line expect(7, wrongValue, 1, any), + + Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs4), + ?line expect(1, Vbs4), + + ok. + + +%%----------------------------------------------------------------- +%% Loop through entire MIB, to make sure that all instrum. funcs +%% works. +%% Load all std mibs that are not loaded by default. +%%----------------------------------------------------------------- +loop_mib(suite) -> []; +loop_mib(Config) when list(Config) -> + ?LOG("loop_mib -> initiate case",[]), + %% snmpa:verbosity(master_agent,debug), + %% snmpa:verbosity(mib_server,info), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]), + ?line load_master_std("SNMP-MPD-MIB"), + ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?DBG("loop_mib -> try",[]), + try_test(loop_mib_1), + ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]), + ?line unload_master("SNMP-MPD-MIB"), + ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + %% snmpa:verbosity(master_agent,log), + %% snmpa:verbosity(mib_server,silence), + ?LOG("loop_mib -> done",[]). + + +loop_mib_2(suite) -> []; +loop_mib_2(Config) when list(Config) -> + ?LOG("loop_mib_2 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_2 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_2 -> load mibs",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_2 -> unload mibs",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?LOG("loop_mib_2 -> done",[]). + + +loop_mib_3(suite) -> []; +loop_mib_3(Config) when list(Config) -> + ?LOG("loop_mib_3 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_3 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_3 -> load mibs",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_3 -> unload mibs",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?LOG("loop_mib_3 -> done",[]). + + +%% Req. As many mibs all possible +loop_mib_1() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_1([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_1(Oid, N) -> + ?DBG("loop_it_1 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_1 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_1 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_1(NOid, N+1); + #pdu{type='get-response', error_status=noSuchName, error_index=1, + varbinds=[_]} -> + ?DBG("loop_it_1 -> done",[]), + N; + + #pdu{type = Type, error_status = Err, error_index = Idx, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs}) + end. + +%% Req. As many mibs all possible +loop_mib_2() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_2([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_2(Oid, N) -> + ?DBG("loop_it_2 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid, value = endOfMibView}]} -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p",[NOid]), + N; + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_2 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_2(NOid, N+1) + end. + + +%%%----------------------------------------------------------------- +%%% Testing of reported bugs and other tickets. +%%%----------------------------------------------------------------- + +reported_bugs(suite) -> + [otp_1128, otp_1129, otp_1131, otp_1162, + otp_1222, otp_1298, otp_1331, otp_1338, + otp_1342, otp_2776, otp_2979, otp_3187, otp_3725]. + +reported_bugs_2(suite) -> + [otp_1128_2, otp_1129_2, otp_1131_2, otp_1162_2, + otp_1222_2, otp_1298_2, otp_1331_2, otp_1338_2, + otp_1342_2, otp_2776_2, otp_2979_2, otp_3187_2]. + +reported_bugs_3(suite) -> + [otp_1128_3, otp_1129_3, otp_1131_3, otp_1162_3, + otp_1222_3, otp_1298_3, otp_1331_3, otp_1338_3, + otp_1342_3, otp_2776_3, otp_2979_3, otp_3187_3, + otp_3542]. + + +%% These are (ticket) test cases where the initiation has to be done +%% individually. +tickets(suite) -> + [otp_4394]. + +%%----------------------------------------------------------------- +%% Ticket: OTP-1128 +%% Slogan: Bug in handling of createAndWait set-requests. +%%----------------------------------------------------------------- +otp_1128(suite) -> []; +otp_1128(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1128), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1128_2(X) -> otp_1128(X). + +otp_1128_3(X) -> otp_1128(X). + +otp_1128() -> + io:format("Testing bug reported in ticket OTP-1128...~n"), + + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + + s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(29, [{NewKeyc5, ?notReady}]), + s([{NewKeyc5, ?active}, {NewKeyc3, 2}]), + ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(31, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(32, [{NewKeyc5, ?destroy}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1129, OTP-1169 +%% Slogan: snmpa:int_to_enum crashes on bad oids +%%----------------------------------------------------------------- +otp_1129(suite) -> []; +otp_1129(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + try_test(otp_1129_i, [node()]), + ?line unload_master("Klas3"). + +otp_1129_2(X) -> otp_1129(X). + +otp_1129_3(X) -> otp_1129(X). + +otp_1129_i(MaNode) -> + io:format("Testing bug reported in ticket OTP-1129...~n"), + false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]), + false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1131 +%% Slogan: Agent crashes / erlang node halts if RowIndex in a +%% setrequest is of bad type, e.g. an INDEX {INTEGER}, +%% and RowIdenx [3,2]. +%%----------------------------------------------------------------- +otp_1131(suite) -> []; +otp_1131(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas1"), + try_test(otp_1131), + ?line unload_master("Klas1"). + +otp_1131_2(X) -> otp_1131(X). + +otp_1131_3(X) -> otp_1131(X). + +otp_1131() -> + io:format("Testing bug reported in ticket OTP-1131...~n"), + s([{[friendsEntry, [2, 3, 1]], s, "kompis3"}, + {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1162 +%% Slogan: snmp_agent can't handle wrongValue from instrum.func +%%----------------------------------------------------------------- +otp_1162(suite) -> []; +otp_1162(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + try_test(otp_1162), + stop_subagent(SA). + +otp_1162_2(X) -> otp_1162(X). + +otp_1162_3(X) -> otp_1162(X). + +otp_1162() -> + s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok) + ?line expect(1, ?v1_2(badValue, wrongValue), 1, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1222 +%% Slogan: snmp agent crash if faulty index is returned from instrum +%%----------------------------------------------------------------- +otp_1222(suite) -> []; +otp_1222(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + ?line load_master("Klas4"), + try_test(otp_1222), + ?line unload_master("Klas3"), + ?line unload_master("Klas4"). + +otp_1222_2(X) -> otp_1222(X). + +otp_1222_3(X) -> otp_1222(X). + +otp_1222() -> + io:format("Testing bug reported in ticket OTP-1222...~n"), + s([{[fStatus4,1], 4}, {[fName4,1], 1}]), + ?line expect(1, genErr, 0, any), + s([{[fStatus4,2], 4}, {[fName4,2], 1}]), + ?line expect(2, genErr, 0, any). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1298 +%% Slogan: Negative INTEGER values are treated as positive. +%%----------------------------------------------------------------- +otp_1298(suite) -> []; +otp_1298(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1298), + ?line unload_master("Klas2"). + +otp_1298_2(X) -> otp_1298(X). + +otp_1298_3(X) -> otp_1298(X). + +otp_1298() -> + io:format("Testing bug reported in ticket OTP-1298...~n"), + s([{[fint,0], -1}]), + ?line expect(1298, [{[fint,0], -1}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1331 +%% Slogan: snmp_generic should return noError when deleting non-ex row +%%----------------------------------------------------------------- +otp_1331(suite) -> []; +otp_1331(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1331), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1331_2(X) -> otp_1331(X). + +otp_1331_3(X) -> otp_1331(X). + +otp_1331() -> + NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")], + s([{NewKeyc5, ?destroy}]), + ?line expect(1, [{NewKeyc5, ?destroy}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1338 +%% Slogan: snmp bug in initialisation of default values for mnesia tabs +%%----------------------------------------------------------------- +otp_1338(suite) -> []; +otp_1338(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1338), + ?line unload_master("Klas2"). + +otp_1338_2(X) -> otp_1338(X). + +otp_1338_3(X) -> otp_1338(X). + +otp_1338() -> + s([{[kStatus2, 7], i, ?createAndGo}]), + ?line expect(1, [{[kStatus2, 7], ?createAndGo}]), + g([[kName2, 7]]), + ?line expect(2, [{[kName2, 7], "JJJ"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1342 +%% Slogan: default impl of snmp table can't handle bad index access, +%% Set when INDEX is read-write gets into an infinite loop! +%%----------------------------------------------------------------- +otp_1342(suite) -> []; +otp_1342(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas4"), + try_test(otp_1342), + ?line unload_master("Klas4"). + +otp_1342_2(X) -> otp_1342(X). + +otp_1342_3(X) -> otp_1342(X). + +otp_1342() -> + s([{[fIndex5, 1], i, 1}, + {[fName5, 1], i, 3}, + {[fStatus5, 1], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1366 +%% Slogan: snmp traps not sent to all managers +%% Note: NYI! We need a way to tell the test server that we need +%% mgrs on two different machines. +%%----------------------------------------------------------------- +otp_1366(suite) -> []; +otp_1366(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1366), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1366_2(X) -> otp_1366(X). + +otp_1366_3(X) -> otp_1366(X). + +otp_1366() -> + ?INF("NOT YET IMPLEMENTED", []), + 'NYI'. + +%%----------------------------------------------------------------- +%% Ticket: OTP-2776 +%% Slogan: snmp:validate_date_and_time() fails when time is 00:00 +%%----------------------------------------------------------------- +otp_2776(suite) -> []; +otp_2776(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_2776). + +otp_2776_2(X) -> otp_2776(X). + +otp_2776_3(X) -> otp_2776(X). + +otp_2776() -> + io:format("Testing bug reported in ticket OTP-2776...~n"), + + Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0], + Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00 + Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0], + Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0], + Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0], + Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0], + Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2 + Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0], + Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4 + Dt10_invalid = [], + Dt11_invalid = [kalle,hobbe], + L = [{ 1, true, Dt01_valid}, + { 2, true, Dt02_valid}, + { 3, true, Dt03_valid}, + { 4, false, Dt04_invalid}, + { 5, true, Dt05_valid}, + { 6, true, Dt06_valid}, + { 7, false, Dt07_invalid}, + { 8, true, Dt08_valid}, + { 9, false, Dt09_invalid}, + {10, false, Dt10_invalid}, + {11, false, Dt11_invalid}], + + ?line ok = validate_dat(L). + + +validate_dat(L) -> validate_dat(L,[]). + +validate_dat([],V) -> + Fun = fun({_,X}) -> case X of + ok -> false; + _ -> true + end + end, + validate_dat1( lists:reverse( lists:filter(Fun,V) ) ); +validate_dat([{Id,E,Dat}|T],V) -> + validate_dat(T,[validate_dat2(Id,E,Dat) | V]). + +validate_dat1([]) -> ok; +validate_dat1(L) -> {error,L}. + +validate_dat2(Id, E, Dat) -> + Res = case {E,snmp:validate_date_and_time(Dat)} of + {E,E} -> ok; + {E,A} -> {E,A} + end, + {Id, Res}. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-2979 +%% Slogan: get-next on more than 1 column in an empty table +%% returns bad response. +%%----------------------------------------------------------------- +otp_2979(suite) -> []; +otp_2979(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Test1"), + ?line init_old(), + try_test(otp_2979), + ?line unload_master("Test1"). + +otp_2979_2(X) -> otp_2979(X). + +otp_2979_3(X) -> otp_2979(X). + +otp_2979() -> + gn([[sparseDescr], [sparseStatus]]), + ?line expect(1, [{[sparseStr,0], "slut"}, + {[sparseStr,0], "slut"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3187 +%% Slogan: get-next on vacmAccessTable for colums > 5 returns +%% endOfTable - should return value. +%%----------------------------------------------------------------- +otp_3187(suite) -> []; +otp_3187(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + otp_3187(), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +otp_3187_2(X) -> otp_3187(X). + +otp_3187_3(X) -> otp_3187(X). + +otp_3187() -> + ?line Elements = + snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]), + lists:foreach(fun(E) -> + ?line if E == endOfTable -> + ?FAIL(endOfTable); + true -> ok + end + end, Elements). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3542 +%% Slogan: +%%----------------------------------------------------------------- +otp_3542(suite) -> []; +otp_3542(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_3542). + +otp_3542() -> + io:format("SNMP v3 discovery...~n"), + ?line Res = snmp_test_mgr:d(), + io:format("SNMP v3 discovery result: ~p~n",[Res]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-3725 +%% Slogan: Slow response time on snmpa:int_to_enum +%%----------------------------------------------------------------- +otp_3725(suite) -> []; +otp_3725(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_3725_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +%% Req. OLD-SNMPEA-MIB +otp_3725_test(MaNode) -> + io:format("Testing feature requested in ticket OTP-3725...~n"), + ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]), + ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]), + ?DBG("otp_3725_test -> Db = ~p",[Db]), + + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [Db, intAgentIpAddress]), + ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name, + [Db,OID]), + ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [Db, [1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [Db, intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum, + [Db, 'RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]), + ok. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-4394 +%% Slogan: Target mib tag list check invalid +%%----------------------------------------------------------------- + + +otp_4394(suite) -> {req, [], {conf, + init_otp_4394, + [otp_4394_test], + finish_otp_4394}}. + +init_otp_4394(Config) when list(Config) -> + ?DBG("init_otp_4394 -> entry with" + "~n Config: ~p", [Config]), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line otp_4394_config(AgentDir, MgrDir, Ip), + MasterAgentVerbosity = {master_agent_verbosity, trace}, + NetIfVerbosity = {net_if_verbosity, trace}, + Opts = [MasterAgentVerbosity,NetIfVerbosity], + [{vsn, v1} | start_v1_agent(Config,Opts)]. + +otp_4394_config(AgentDir, MgrDir, Ip0) -> + ?DBG("otp_4394_config -> entry with" + "~n AgentDir: ~p" + "~n MgrDir: ~p" + "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]), + Vsn = [v1], + Ip = tuple_to_list(Ip0), + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip, + ?TRAP_UDP, Ip, 4000, + "OTP-4394 test"), + ?line case update_usm(Vsn, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsn, MgrDir); + false -> + ?line ok + end, + C1 = {"a", "all-rights", "initial", "", "pc"}, + C2 = {"c", "secret", "secret_name", "", "secret_tag"}, + ?line write_community_conf(AgentDir, [C1, C2]), + ?line update_vacm(Vsn, AgentDir), + Ta1 = {"shelob v1", + [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda + "pc1", + "target_v1", "", + %% [255,255,255,255,0,0], + [], + 2048}, + Ta2 = {"bifur v1", + [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip + "pc2", + "target_v1", "", + %% [255,255,255,255,0,0], + [], 2048}, + ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]), + ?line write_target_params_conf(AgentDir, Vsn), + ?line write_notify_conf(AgentDir), + ok. + + + +finish_otp_4394(Config) when list(Config) -> + ?DBG("finish_otp_4394 -> entry", []), + C1 = stop_agent(Config), + delete_files(C1), + erase(mgr_node), + lists:keydelete(vsn, 1, C1). + +otp_4394_test(suite) -> []; +otp_4394_test(Config) -> + ?DBG("otp_4394_test -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_4394_test1), + ?DBG("otp_4394_test -> done", []), + ok. + +otp_4394_test1() -> + ?DBG("otp_4394_test1 -> entry", []), + gn([[1,1]]), + Res = + case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of + %% {error, 1, {"?",[]}, {"~w",[timeout]}} + {error, 1, _, {_, [timeout]}} -> + ?DBG("otp_4394_test1 -> expected result: timeout", []), + ok; + Else -> + Else + end, + ?DBG("otp_4394_test1 -> done with: ~p", [Res]), + Res. + + +%%%-------------------------------------------------- +%%% Used to test the standard mib with our +%%% configuration. +%%%-------------------------------------------------- +run(F, A, Opts) -> + M = get(mib_dir), + Dir = get(mgr_dir), + User = snmp_misc:get_option(user, Opts, "all-rights"), + SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv), + EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"), + CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID), + Community = snmp_misc:get_option(community, Opts, "all-rights"), + ?DBG("run -> start crypto app",[]), + Crypto = case os:type() of + vxworks -> + no_crypto; + _ -> + ?CRYPTO_START() + end, + ?DBG("run -> Crypto: ~p",[Crypto]), + catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + ?DBG("run -> config:~n" + "\tM: ~p~n" + "\tDir: ~p~n" + "\tUser: ~p~n" + "\tSecLevel: ~p~n" + "\tEngineID: ~p~n" + "\tCtxEngineID: ~p~n" + "\tCommunity: ~p~n" + "\tStdM: ~p", + [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]), + case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()}, + {packet_server_debug,true}, + {debug,true}, + {agent, get(master_host)}, + {agent_udp, 4000}, + {trap_udp, 5000}, + {recbuf,65535}, + quiet, + get(vsn), + {community, Community}, + {user, User}, + {sec_level, SecLevel}, + {engine_id, EngineID}, + {context_engine_id, CtxEngineID}, + {dir, Dir}, + {mibs, mibs(StdM, M)}]) of + {ok, _Pid} -> + Res = apply(?MODULE, F, A), + catch snmp_test_mgr:stop(), + Res; + Err -> + io:format("Error starting manager: ~p\n", [Err]), + catch snmp_test_mgr:stop(), + ?line exit({mgr_start, Err}) + end. + + +mibs(StdMibDir,MibDir) -> + [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")), + join(MibDir, "OLD-SNMPEA-MIB.bin"), + join(StdMibDir, "SNMP-FRAMEWORK-MIB"), + join(StdMibDir, "SNMP-MPD-MIB"), + join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"), + join(StdMibDir, "SNMP-USER-BASED-SM-MIB"), + join(StdMibDir, "SNMP-TARGET-MIB"), + join(StdMibDir, "SNMP-NOTIFICATION-MIB"), + join(MibDir, "Klas1.bin"), + join(MibDir, "Klas2.bin"), + join(MibDir, "Klas3.bin"), + join(MibDir, "Klas4.bin"), + join(MibDir, "SA-MIB.bin"), + join(MibDir, "TestTrap.bin"), + join(MibDir, "Test1.bin"), + join(MibDir, "Test2.bin"), + join(MibDir, "TestTrapv2.bin")]. + +join(D,F) -> + filename:join(D,F). + +%% string used in index +is(S) -> [length(S) | S]. + +try_test(Func) -> + call(get(mgr_node), ?MODULE, run, [Func, [], []]). + +try_test(Func, A) -> + call(get(mgr_node), ?MODULE, run, [Func, A, []]). + +try_test(Func, A, Opts) -> + call(get(mgr_node), ?MODULE, run, [Func, A, Opts]). + +call(N,M,F,A) -> + ?DBG("call -> entry with~n" + " N: ~p~n" + " M: ~p~n" + " F: ~p~n" + " A: ~p~n" + " when~n" + " get(): ~p", + [N,M,F,A,get()]), + spawn(N, ?MODULE, wait, [self(),get(),M,F,A]), + receive + {done, {'EXIT', Rn}, Loc} -> + ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]), + put(test_server_loc, Loc), + exit(Rn); + {done, Ret, Zed} -> + ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]), + Ret + end. + +wait(From, Env, M, F, A) -> + ?DBG("wait -> entry with ~n" + "\tFrom: ~p~n" + "\tEnv: ~p",[From,Env]), + lists:foreach(fun({K,V}) -> put(K,V) end, Env), + Rn = (catch apply(M, F, A)), + ?DBG("wait -> Rn: ~n~p", [Rn]), + From ! {done, Rn, get(test_server_loc)}, + exit(Rn). + +expect(A,B) -> ok = snmp_test_mgr:expect(A,B). +expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C). +expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D). +expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F). + +get_req(Id, Vars) -> + ?DBG("get_req -> entry with~n" + "\tId: ~p~n" + "\tVars: ~p",[Id,Vars]), + g(Vars), + ?DBG("get_req -> await response",[]), + {ok, Val} = snmp_test_mgr:get_response(Id, Vars), + ?DBG("get_req -> response: ~p",[Val]), + Val. + +get_next_req(Vars) -> + ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]), + gn(Vars), + ?DBG("get_next_req -> await response",[]), + Response = snmp_test_mgr:receive_response(), + ?DBG("get_next_req -> response: ~p",[Response]), + Response. + + + +start_node(Name) -> + ?LOG("start_node -> entry with Name: ~p",[Name]), + M = list_to_atom(?HOSTNAME(node())), + ?DBG("start_node -> M: ~p",[M]), + Pa = filename:dirname(code:which(?MODULE)), + ?DBG("start_node -> Pa: ~p",[Pa]), + + Args = case init:get_argument('CC_TEST') of + {ok, [[]]} -> + " -pa /clearcase/otp/libraries/snmp/ebin "; + {ok, [[Path]]} -> + " -pa " ++ Path; + error -> + "" + end, + %% Do not use start_link!!! (the proc that calls this one is tmp) + ?DBG("start_node -> Args: ~p~n",[Args]), + A = Args ++ " -pa " ++ Pa, + case (catch ?START_NODE(Name, A)) of + {ok, Node} -> + %% Tell the test_server to not clean up things it never started. + ?DBG("start_node -> Node: ~p",[Node]), + {ok, Node}; + Else -> + ?ERR("start_node -> failed with(other): Else: ~p",[Else]), + ?line ?FAIL(Else) + end. + + +stop_node(Node) -> + ?LOG("stop_node -> Node: ~p",[Node]), + rpc:cast(Node, erlang, halt, []). + +p(X) -> + io:format(user, X++"\n", []). + +sleep(X) -> + receive + after + X -> ok + end. + +%%%----------------------------------------------------------------- +%%% Configuration +%%%----------------------------------------------------------------- +config(Vsns, MgrDir, AgentDir, MIp, AIp) -> + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp, + ?TRAP_UDP, AIp, 4000, + "test"), + ?line case update_usm(Vsns, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsns, MgrDir); + false -> + ?line ok + end, + ?line update_community(Vsns, AgentDir), + ?line update_vacm(Vsns, AgentDir), + ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns), + ?line write_target_params_conf(AgentDir, Vsns), + ?line write_notify_conf(AgentDir), + ok. + +delete_files(Config) -> + Dir = ?config(agent_dir, Config), + {ok, List} = file:list_dir(Dir), + lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end, + List). + +update_usm(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +update_usm_mgr(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +rewrite_usm_mgr(Dir, ShaKey, DesKey) -> + ?line ok = file:rename(filename:join(Dir,"usm.conf"), + filename:join(Dir,"usm.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + file:close(Fid). + +reset_usm_mgr(Dir) -> + ?line ok = file:rename(filename:join(Dir,"usm.old"), + filename:join(Dir,"usm.conf")). + + +update_community([v3], _Dir) -> ok; +update_community(_, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n", + []), + file:close(Fid). + + +-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]). +update_vacm(_Vsn, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]), + ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", " + "~w, excluded, null}.\n", [?tDescr_instance]), + file:close(Fid). + + +vacm_ver(v1) -> v1; +vacm_ver(v2) -> v2c; +vacm_ver(v3) -> usm. + + +write_community_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write), + ok = write_community_conf1(Fid, Confs), + file:close(Fid). + +write_community_conf1(_, []) -> + ok; +write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) -> + ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n", + [ComIdx, ComName, SecName, CtxName, TransTag]), + write_community_conf1(Fid, Confs). + + +write_target_addr_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + ok = write_target_addr_conf1(Fid, Confs), + file:close(Fid). + + +write_target_addr_conf1(_, []) -> + ok; +write_target_addr_conf1(Fid, + [{Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz}|Confs]) -> + ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", + [Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz]), + write_target_addr_conf1(Fid, Confs). + +write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + lists:foreach(fun(Vsn) -> + ok = io:format(Fid, + "{\"~s\", ~w, ~w, 1500, 3, " + "\"std_trap\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, mk_param(Vsn)]), + case Vsn of + v1 -> ok; + v2 -> + ok = io:format(Fid, + "{\"~s.2\",~w,~w,1500,3, " + "\"std_inform\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]); + v3 -> + ok = io:format(Fid, + "{\"~s.3\",~w,~w,1500,3, " + "\"std_inform\", \"~s\", " + "\"mgrEngine\", [], 1024}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]) + end + end, + Vsns), + file:close(Fid). + +mk_param(v1) -> "target_v1"; +mk_param(v2) -> "target_v2"; +mk_param(v3) -> "target_v3". + +mk_ip([A,B,C,D], Vsn) -> + io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]). + + +rewrite_target_addr_conf(Dir,NewPort) -> + TAFile = filename:join(Dir, "target_addr.conf"), + ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]), + case file:read_file_info(TAFile) of + {ok, _} -> ok; + {error, R} -> ?ERR("failure reading file info of " + "target address config file: ~p",[R]), + ok + end, + + ?line [TrapAddr|Addrs] = + snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end), + + ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]), + + NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs], + + ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]), + + ?line ok = file:rename(filename:join(Dir,"target_addr.conf"), + filename:join(Dir,"target_addr.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + + ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs), + + file:close(Fid). + +rewrite_target_addr_conf1(O) -> + {ok,O}. + +rewrite_target_addr_conf2(NewPort,{Name,Ip,_Port,Timeout,Retry, + "std_trap",EngineId}) -> + ?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]), + {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; +rewrite_target_addr_conf2(_NewPort,O) -> + ?LOG("rewrite_target_addr_conf2 -> entry with " + "~n O: ~p",[O]), + O. + + +rewrite_target_addr_conf3(_,[]) -> ok; +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry, + ParamName,EngineId}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % ParamsName + "\"~s\"}.", % EngineId + [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]), + rewrite_target_addr_conf3(Fid,T); +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList, + ParamName,EngineId,TMask,MMS}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % TagList + "\"~s\", " % ParamsName + "\"~s\"," % EngineId + "~p, " % TMask + "~p}.", % MMS + [Name,Ip,Port,Timeout,Retry,TagList,ParamName, + EngineId,TMask,MMS]), + rewrite_target_addr_conf3(Fid,T). + +reset_target_addr_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_addr.old"), + filename:join(Dir,"target_addr.conf")). + +write_target_params_conf(Dir, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + lists:foreach(fun(Vsn) -> + MP = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> v3 + end, + SM = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> usm + end, + ok = io:format(Fid, "{\"target_~w\", ~w, ~w, " + "\"all-rights\", noAuthNoPriv}.~n", + [Vsn, MP, SM]) + end, + Vsns), + file:close(Fid). + +rewrite_target_params_conf(Dir, SecName, SecLevel) -> + ?line ok = file:rename(filename:join(Dir,"target_params.conf"), + filename:join(Dir,"target_params.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n", + [SecName, SecLevel]), + file:close(Fid). + +reset_target_params_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_params.old"), + filename:join(Dir,"target_params.conf")). + +write_notify_conf(Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write), + ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []), + ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []), + file:close(Fid). + +ver_to_trap_str([v1]) -> "v1"; +ver_to_trap_str([v2]) -> "v2"; +% default is to use the latest snmp version +ver_to_trap_str([v1,v2]) -> "v2". + + + +write_view_conf(Dir) -> + {ok, Fid} = file:open(a(Dir,"view.conf"),write), + ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []), + ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]), + file:close(Fid). + +a(A,B) -> lists:append(A,B). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +copy_file(From, To) -> + {ok, Bin} = file:read_file(From), + ok = file:write_file(To, Bin). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +display_memory_usage() -> + Info = snmpa:info(snmp_master_agent), + TreeSize = lists_key1search(tree_size_bytes, Info), + ProcMem = lists_key1search(process_memory, Info), + MibDbSize = lists_key1search([db_memory,mib], Info), + NodeDbSize = lists_key1search([db_memory,node], Info), + TreeDbSize = lists_key1search([db_memory,tree], Info), + ?INF("Memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p", + [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]). + +lists_key1search([], Res) -> + Res; +lists_key1search([Key|Keys], List) when atom(Key), list(List) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + lists_key1search(Keys, Val); + false -> + undefined + end; +lists_key1search(Key, List) when atom(Key) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + Val; + false -> + undefined + end. + + +regs() -> + lists:sort(registered()). diff --git a/lib/snmp/test/snmp_agent_mt_test.erl b/lib/snmp/test/snmp_agent_mt_test.erl new file mode 100644 index 0000000000..8d5a57f58d --- /dev/null +++ b/lib/snmp/test/snmp_agent_mt_test.erl @@ -0,0 +1,5657 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_agent_mt_test). + +%% TODO +%% * Test fault-tolerance (kill master etc) +%% + +-compile(export_all). + +-define(application, snmp). + +-include_lib("kernel/include/file.hrl"). +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). +%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl"). + + +-define(klas1, [1,3,6,1,2,1,7]). +-define(klas2, [1,3,6,1,2,1,9]). +-define(klas3, [1,3,6,1,2,1,8,1]). +-define(klas4, [1,3,6,1,2,1,8,4]). +-define(sa, [1,3,6,1,4,1,193,2]). +-define(system, [1,3,6,1,2,1,1]). +-define(snmp, [1,3,6,1,2,1,11]). +-define(snmpTraps, [1,3,6,1,6,3,1,1,5]). +-define(ericsson, [1,3,6,1,4,1,193]). +-define(testTrap, [1,3,6,1,2,1,15,0]). +-define(xDescr, [1,3,6,1,2,1,17,1]). +-define(xDescr2, [1,3,6,1,2,1,17,2]). + +-define(active, 1). +-define(notInService, 2). +-define(notReady, 3). +-define(createAndGo, 4). +-define(createAndWait, 5). +-define(destroy, 6). + +-define(TRAP_UDP, 5000). + +-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"). + +-define(str(X), snmp_pdus:bits_to_str(X)). + +-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n", + [?LINE, self()]), + receive cont -> ok end + end). + + +-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]). +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + +-define(v1_2_3(V1,V2,V3), + case get(vsn) of + v1 -> V1; + v2 -> V2; + _ -> V3 + end). + +all(suite) -> {req, + [mnesia, distribution, + {local_slave_nodes, 2}, {time, 360}], + [{conf, init_all, cases(), finish_all}]}. + +init_per_testcase(_Case, Config) when list(Config) -> + Dog = ?t:timetrap(?t:minutes(6)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + Config. + +cases() -> + case ?OSTYPE() of + vxworks -> + %% No crypto app, so skip v3 testcases + [ + app_info, + test_v1, test_v2, test_v1_v2, + test_multi_threaded, + mib_storage, + tickets]; + _Else -> + [ + app_info, + test_v1, test_v2, test_v1_v2, test_v3, + test_multi_threaded, + mib_storage, + tickets + ] + end. + + +%%%----------------------------------------------------------------- +%%% The test case structure is as follows: +%%% +%%% init_all - starts mnesia, +%%% +%%% init_v1 - starts agent +%%% simple +%%% big - e.g. starts/stops subagent, load/unloads mibs +%%% init_mul +%%% mul_get +%%% mul_set +%%% <etc> +%%% finish_mul +%%% <etc> +%%% finish_v1 +%%% +%%% init_v2 - starts agent +%%% finish_v2 +%%% +%%% init_bilingual - starts agent +%%% finish_bilingual +%%% +%%% finish_all +%%% +%%% There is still one problem with these testsuites. If one test +%%% fails, it may not be possible to run some other cases, as it +%%% may have e.g. created some row or loaded some table, that it +%%% didn't undo (since it failed). +%%%----------------------------------------------------------------- + +init_all(Config0) when list(Config0) -> + ?LOG("init_all -> entry with" + "~n Config0: ~p",[Config0]), + + %% -- + %% Fix config: + %% + + DataDir0 = ?config(data_dir, Config0), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + Config1 = lists:keydelete(data_dir, 1, Config0), + Config = [{data_dir, DataDir3 ++ "/"}|Config1], + + %% -- + %% Start nodes + %% + + ?line {ok, SaNode} = start_node(snmp_sa), + ?line {ok, MgrNode} = start_node(snmp_mgr), + + + %% -- + %% Create necessary files + %% + + Dir = ?config(priv_dir, Config), + ?DBG("init_all -> Dir ~p", [Dir]), + + DataDir = ?config(data_dir, Config), + ?DBG("init_all -> DataDir ~p", [DataDir]), + + file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")), + ?DBG("init_all -> MgrDir ~p", [MgrDir]), + + file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")), + ?DBG("init_all -> AgentDir ~p", [AgentDir]), + + file:make_dir(SaDir = filename:join(Dir, "sa_dir/")), + ?DBG("init_all -> SaDir ~p", [SaDir]), + + + %% -- + %% Start and initiate mnesia + %% + + ?DBG("init_all -> load application mnesia", []), + ?line ok = application:load(mnesia), + + ?DBG("init_all -> load application mnesia on node ~p", [SaNode]), + ?line ok = rpc:call(SaNode, application, load, [mnesia]), + + ?DBG("init_all -> application mnesia: set_env dir",[]), + ?line application_controller:set_env(mnesia, dir, + filename:join(Dir, "Mnesia1")), + + ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]), + ?line rpc:call(SaNode, application_controller, set_env, + [mnesia, dir, filename:join(Dir, "Mnesia2")]), + + ?DBG("init_all -> create mnesia schema",[]), + ?line ok = mnesia:create_schema([SaNode, node()]), + + ?DBG("init_all -> start application mnesia",[]), + ?line ok = application:start(mnesia), + + ?DBG("init_all -> start application mnesia on ~p",[SaNode]), + ?line ok = rpc:call(SaNode, application, start, [mnesia]), + Ip = ?LOCALHOST(), + [{snmp_sa, SaNode}, + {snmp_mgr, MgrNode}, + {agent_dir, AgentDir ++ "/"}, + {mgr_dir, MgrDir ++ "/"}, + {sa_dir, SaDir ++ "/"}, + {mib_dir, DataDir}, + {ip, Ip} | + Config]. + +finish_all(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + stop_node(SaNode), + stop_node(MgrNode), + application:stop(mnesia). + +start_v1_agent(Config) when list(Config) -> + start_agent(Config, [v1]). + +start_v1_agent(Config,Opts) when list(Config), list(Opts) -> + start_agent(Config, [v1], Opts). + +start_v2_agent(Config) when list(Config) -> + start_agent(Config, [v2]). + +start_v3_agent(Config) when list(Config) -> + start_agent(Config, [v3]). + +start_bilingual_agent(Config) when list(Config) -> + start_agent(Config, [v1,v2]). + +start_multi_threaded_agent(Config) when list(Config) -> + start_agent(Config, [v2], [{snmp_multi_threaded, true}]). + +stop_agent(Config) when list(Config) -> + ?LOG("stop_agent -> entry with" + "~n Config: ~p",[Config]), + + {Sup, Par} = ?config(snmp_sup, Config), + ?DBG("stop_agent -> attempt to stop (sup) ~p" + "~n Sup: ~p" + "~n Par: ~p", + [Sup, + (catch process_info(Sup)), + (catch process_info(Par))]), + stop_sup(Sup, Par), + + {Sup2, Par2} = ?config(snmp_sub, Config), + ?DBG("stop_agent -> attempt to stop (sub) ~p" + "~n Sup2: ~p" + "~n Par2: ~p", + [Sup2, + (catch process_info(Sup2)), + (catch process_info(Par2))]), + stop_sup(Sup2, Par2), + + ?DBG("stop_agent -> done - now cleanup config", []), + C1 = lists:keydelete(snmp_sup, 1, Config), + lists:keydelete(snmp_sub, 1, C1). + + +stop_sup(Pid, _) when node(Pid) == node() -> + case (catch process_info(Pid)) of + PI when list(PI) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + exit(Pid, kill), + await_stopped(Pid, Ref); + {'EXIT', _Reason} -> + ?LOG("stop_sup -> ~p not running", [Pid]), + ok + end; +stop_sup(Pid, _) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + ?LOG("stop_sup -> Ref: ~p", [Ref]), + %% Pid ! {'EXIT', Parent, shutdown}, % usch + exit(Pid, kill), + await_stopped(Pid, Ref). + +await_stopped(Pid, Ref) -> + receive + {'DOWN', Ref, process, Pid, _Reason} -> + ?DBG("received down message for ~p", [Pid]), + ok + after 10000 -> + ?INF("await_stopped -> timeout for ~p",[Pid]), + erlang:demonitor(Ref), + ?FAIL({failed_stop,Pid}) + end. + + +start_agent(Config, Vsn) -> + start_agent(Config, Vsn, []). +start_agent(Config, Vsn, Opts) -> + ?LOG("start_agent -> entry (~p) with" + "~n Config: ~p" + "~n Vsn: ~p" + "~n Opts: ~p",[node(), Config, Vsn, Opts]), + + ?line AgentDir = ?config(agent_dir, Config), + ?line SaNode = ?config(snmp_sa, Config), + + snmp_app_env_init(vsn_init(Vsn) ++ + [{audit_trail_log, read_write_log}, + {audit_trail_log_dir, AgentDir}, + {audit_trail_log_size, {10240, 10}}, + {force_config_reload, false}, + {snmp_agent_type, master}, + {snmp_config_dir, AgentDir}, + {snmp_db_dir, AgentDir}, + {snmp_local_db_auto_repair, true}, + {snmp_master_agent_verbosity, trace}, + {snmp_supervisor_verbosity, trace}, + {snmp_mibserver_verbosity, trace}, + {snmp_symbolic_store_verbosity, trace}, + {snmp_note_store_verbosity, trace}, + {snmp_net_if_verbosity, trace}], + Opts), + + + process_flag(trap_exit,true), + + {ok, AppSup} = snmp_app_sup:start_link(), + unlink(AppSup), + ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]), + + ?DBG("start_agent -> start master agent (old style)",[]), + Sup = case (catch snmpa_app:start(normal)) of + {ok, S} -> + ?DBG("start_agent -> started, Sup: ~p",[S]), + S; + + Else -> + ?DBG("start_agent -> unknown result: ~n~p",[Else]), + %% Get info about the apps we depend on + MnesiaInfo = mnesia_running(), + ?FAIL({start_failed,Else,MnesiaInfo}) + end, + + ?DBG("start_agent -> unlink from supervisor",[]), + ?line unlink(Sup), + ?line SaDir = ?config(sa_dir, Config), + ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]), + ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]), + ?DBG("start_agent -> done",[]), + ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config]. + + +vsn_init(Vsn) -> + vsn_init([v1,v2,v3], Vsn, []). + +vsn_init([], _Vsn, Acc) -> + Acc; +vsn_init([V|Vsns], Vsn, Acc) -> + case lists:member(V, Vsn) of + true -> + vsn_init(Vsns, Vsn, [{V, true}|Acc]); + false -> + vsn_init(Vsns, Vsn, [{V, false}|Acc]) + end. + +snmp_app_env_init(Env0, Opts) -> + ?DBG("snmp_app_env_init -> unload snmp",[]), + ?line application:unload(snmp), + ?DBG("snmp_app_env_init -> load snmp",[]), + ?line application:load(snmp), + ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]), + F1 = fun({Key,Val} = New, Acc0) -> + ?DBG("snmp_app_env_init -> " + "updating setting ~p to ~p", [Key, Val]), + case lists:keyreplace(Key, 1, Acc0, New) of + Acc0 -> + [New|Acc0]; + Acc -> + Acc + end + end, + Env = lists:foldr(F1, Env0, Opts), + ?DBG("snmp_app_env_init -> Env: ~p",[Env]), + F2 = fun({Key,Val}) -> + ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]), + application_controller:set_env(snmp, Key, Val) + end, + lists:foreach(F2, Env). + + + + +%% Test if application is running +mnesia_running() -> ?IS_MNESIA_RUNNING(). +crypto_running() -> ?IS_CRYPTO_RUNNING(). + + +start_sub(Dir) -> + ?DBG("start_sub -> entry",[]), + Opts = [{db_dir, Dir}, + {supervisor, [{verbosity, trace}]}], + %% BMK BMK +% {ok, P} = snmp_supervisor:start_sub(Dir), + {ok, P} = snmpa_supervisor:start_sub_sup(Opts), + unlink(P), + {ok, {P, self()}}. + +create_tables(SaNode) -> + ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables}, + {attributes, [a1,a2]}]). + +delete_tables() -> + mnesia:delete_table(friendsTable2), + mnesia:delete_table(kompissTable2), + mnesia:delete_table(snmp_variables). + +%% Creation is done in runtime! +delete_mib_storage_mnesia_tables() -> + mnesia:delete_table(snmpa_mib_data), + mnesia:delete_table(snmpa_mib_tree), + mnesia:delete_table(snmpa_symbolic_store). + +%%----------------------------------------------------------------- +%% A test case is always one of: +%% - v1 specific case +%% - v2 specific case +%% - v1 and v2 case +%% All v1 specific cases are prefixed with v1_, and all v2 with +%% v2_. E.g. v1_trap/v2_trap. +%% +%% All other cases are shared. However, the testserver uses the name +%% of the case to generate a file for that case. The same case cannot +%% be used in different configurations in the same suite. Therefore +%% all these functions exists in two variants, the base function +%% <base>, and a second version <base>_2. There may be several +%% versions as well, <base>_N. +%%----------------------------------------------------------------- +mib_storage(suite) -> [ + mib_storage_ets, + mib_storage_dets, + mib_storage_mnesia, + mib_storage_size_check_ets, + mib_storage_size_check_dets, + mib_storage_size_check_mnesia, + mib_storage_varm_dets, + mib_storage_varm_mnesia + ]. + +mib_storage_ets(suite) -> {req, [], {conf, init_mib_storage_ets, + mib_storage_ets_cases(), + finish_mib_storage_ets}}. + +mib_storage_dets(suite) -> {req, [], {conf, init_mib_storage_dets, + mib_storage_dets_cases(), + finish_mib_storage_dets}}. + +mib_storage_mnesia(suite) -> {req, [], {conf, init_mib_storage_mnesia, + mib_storage_mnesia_cases(), + finish_mib_storage_mnesia}}. + +mib_storage_size_check_ets(suite) -> + {req, [], {conf, + init_size_check_mse, + mse_size_check_cases(), + finish_size_check_mse}}. + +mib_storage_size_check_dets(suite) -> + {req, [], {conf, + init_size_check_msd, + msd_size_check_cases(), + finish_size_check_msd}}. + +mib_storage_size_check_mnesia(suite) -> + {req, [], {conf, + init_size_check_msm, + msm_size_check_cases(), + finish_size_check_msm}}. + +mib_storage_varm_dets(suite) -> + {req, [], {conf, + init_varm_mib_storage_dets, + varm_mib_storage_dets_cases(), + finish_varm_mib_storage_dets}}. + +mib_storage_varm_mnesia(suite) -> + {req, [], {conf, + init_varm_mib_storage_mnesia, + varm_mib_storage_mnesia_cases(), + finish_varm_mib_storage_mnesia}}. + +mib_storage_ets_cases() -> + [ + mse_simple, + mse_v1_processing, + mse_big, + mse_big2, + mse_loop_mib, + mse_api, + mse_sa_register, + mse_v1_trap, + mse_sa_error, + mse_next_across_sa, + mse_undo, + mse_standard_mib, + mse_community_mib, + mse_framework_mib, + mse_target_mib, + mse_notification_mib, + mse_view_based_acm_mib, + mse_sparse_table, + mse_me_of, + mse_mib_of]. + +mib_storage_dets_cases() -> + [ + msd_simple, + msd_v1_processing, + msd_big, + msd_big2, + msd_loop_mib, + msd_api, + msd_sa_register, + msd_v1_trap, + msd_sa_error, + msd_next_across_sa, + msd_undo, + msd_standard_mib, + msd_community_mib, + msd_framework_mib, + msd_target_mib, + msd_notification_mib, + msd_view_based_acm_mib, + msd_sparse_table, + msd_me_of, + msd_mib_of + ]. + +mib_storage_mnesia_cases() -> + [ + msm_simple, + msm_v1_processing, + msm_big, + msm_big2, + msm_loop_mib, + msm_api, + msm_sa_register, + msm_v1_trap, + msm_sa_error, + msm_next_across_sa, + msm_undo, + msm_standard_mib, + msm_community_mib, + msm_framework_mib, + msm_target_mib, + msm_notification_mib, + msm_view_based_acm_mib, + msm_sparse_table, + msm_me_of, + msm_mib_of + ]. + +mse_size_check_cases() -> + [mse_size_check]. + +msd_size_check_cases() -> + [msd_size_check]. + +msm_size_check_cases() -> + [msm_size_check]. + +varm_mib_storage_dets_cases() -> + [msd_varm_mib_start]. + +varm_mib_storage_mnesia_cases() -> + [msm_varm_mib_start]. + +init_mib_storage_ets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,ets}, + init_ms(Config, [MibStorage]). + +init_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + init_ms(Config, [MibStorage]). + +init_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + init_ms(Config, [MibStorage]). + +init_ms(Config, Opts) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts], + [{vsn, v1} | start_v1_agent(Config,Opts1)]. + +init_size_check_mse(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, ets}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msd(Config) when list(Config) -> + AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage, {dets, AgentDir}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msm(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, {mnesia,[]}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_ms(Config, Opts) when list(Config) -> + SaNode = ?GCONF(snmp_sa, Config), + %% We are using v3 here, so crypto must be supported or else... + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + create_tables(SaNode), + AgentDir = ?GCONF(agent_dir, Config), + MgrDir = ?GCONF(mgr_dir, Config), + Ip = ?GCONF(ip, Config), + ?line ok = + config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_agent(Config, [v3], Opts)]. + +init_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_dets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +init_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_mnesia -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +finish_mib_storage_ets(Config) when list(Config) -> + ?LOG("finish_mib_storage_ets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_mib_storage_dets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_dets -> entry", []), + delete_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_size_check_mse(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msd(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msm(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_ms(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + + +%% These are just interface functions to fool the test server +mse_simple(X) -> simple(X). +mse_v1_processing(X) -> v1_processing(X). +mse_big(X) -> big(X). +mse_big2(X) -> big2(X). +mse_loop_mib(X) -> loop_mib(X). +mse_api(X) -> api(X). +mse_sa_register(X) -> sa_register(X). +mse_v1_trap(X) -> v1_trap(X). +mse_sa_error(X) -> sa_error(X). +mse_next_across_sa(X) -> next_across_sa(X). +mse_undo(X) -> undo(X). +mse_standard_mib(X) -> snmp_standard_mib(X). +mse_community_mib(X) -> snmp_community_mib(X). +mse_framework_mib(X) -> snmp_framework_mib(X). +mse_target_mib(X) -> snmp_target_mib(X). +mse_notification_mib(X) -> snmp_notification_mib(X). +mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +mse_sparse_table(X) -> sparse_table(X). +mse_me_of(X) -> ms_me_of(X). +mse_mib_of(X) -> ms_mib_of(X). + +msd_simple(X) -> simple(X). +msd_v1_processing(X) -> v1_processing(X). +msd_big(X) -> big(X). +msd_big2(X) -> big2(X). +msd_loop_mib(X) -> loop_mib(X). +msd_api(X) -> api(X). +msd_sa_register(X) -> sa_register(X). +msd_v1_trap(X) -> v1_trap(X). +msd_sa_error(X) -> sa_error(X). +msd_next_across_sa(X) -> next_across_sa(X). +msd_undo(X) -> undo(X). +msd_standard_mib(X) -> snmp_standard_mib(X). +msd_community_mib(X) -> snmp_community_mib(X). +msd_framework_mib(X) -> snmp_framework_mib(X). +msd_target_mib(X) -> snmp_target_mib(X). +msd_notification_mib(X) -> snmp_notification_mib(X). +msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msd_sparse_table(X) -> sparse_table(X). +msd_me_of(X) -> ms_me_of(X). +msd_mib_of(X) -> ms_mib_of(X). + +msm_simple(X) -> simple(X). +msm_v1_processing(X) -> v1_processing(X). +msm_big(X) -> big(X). +msm_big2(X) -> big2(X). +msm_loop_mib(X) -> loop_mib(X). +msm_api(X) -> api(X). +msm_sa_register(X) -> sa_register(X). +msm_v1_trap(X) -> v1_trap(X). +msm_sa_error(X) -> sa_error(X). +msm_next_across_sa(X) -> next_across_sa(X). +msm_undo(X) -> undo(X). +msm_standard_mib(X) -> snmp_standard_mib(X). +msm_community_mib(X) -> snmp_community_mib(X). +msm_framework_mib(X) -> snmp_framework_mib(X). +msm_target_mib(X) -> snmp_target_mib(X). +msm_notification_mib(X) -> snmp_notification_mib(X). +msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msm_sparse_table(X) -> sparse_table(X). +msm_me_of(X) -> ms_me_of(X). +msm_mib_of(X) -> ms_mib_of(X). + + +mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X). +msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X). +msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X). + +msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X). +msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X). + +ms_size_check(suite) -> []; +ms_size_check(Config) when list(Config) -> + p("ms_size_check..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?LOG("mib server size check...", []), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMPv2-MIB"), + ?line load_master_std("SNMPv2-TM"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMPv2-MIB"), + ?line unload_master("SNMPv2-TM"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + + +varm_mib_start(suite) -> []; +varm_mib_start(Config) when list(Config) -> + p("varm_mib_start..."), + ?LOG("varm_mib_start -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + %% Start the agent + Opts = ?GCONF(agent_opts, Config), + Config1 = start_v1_agent(Config, Opts), + + %% Sleep some in order for the agent to start properly + ?DBG("varm_mib_start -> sleep some (before loading mobs)", []), + ?SLEEP(5000), + + %% Load all the mibs + HardwiredMibs = loaded_mibs(), + ?DBG("varm_mib_start -> load all mibs", []), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + + %% Unload the hardwired mibs + ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []), + ?SLEEP(1000), + ?DBG("varm_mib_start -> unload (hardwired) mibs", []), + ?line unload_mibs(HardwiredMibs), %% unload hardwired + + ?DBG("varm_mib_start -> sleep some (before stopping agent)", []), + ?SLEEP(1000), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + Config2 = stop_agent(Config1), + + %% Sleep some in order for the agent to stop properly + ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []), + ?SLEEP(5000), + + %% Start the agent (again) + ?DBG("varm_mib_start -> start the agent", []), + Config3 = start_v1_agent(Config2, Opts), + + ?DBG("varm_mib_start -> sleep some (before starting tests)", []), + ?SLEEP(5000), + + %% Perform the test(s) + ?DBG("varm_mib_start -> perform the tests", []), + try_test(snmp_community_mib), + try_test(snmp_framework_mib), + try_test(snmp_target_mib), + try_test(snmp_notification_mib), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + stop_agent(Config3), + ok. + + +-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]). +-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]). +-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +ms_me_of(suite) -> []; +ms_me_of(Config) when list(Config) -> + p("ms_me_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = me_of(?snmpTrapCommunity_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = me_of(?vacmViewSpinLock_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +me_of(Oid) -> + case snmpa:me_of(Oid) of + {ok, #me{oid = Oid}} -> + ok; + {ok, #me{oid = OtherOid}} -> + case lists:reverse(Oid) of + [0|Rest] -> + case lists:reverse(Rest) of + OtherOid -> + ok; + AnotherOid -> + {error, {invalid_oid, Oid, AnotherOid}} + end; + _ -> + {error, {invalid_oid, Oid, OtherOid}} + end; + {error, Reason} -> + {error, Reason}; + Else -> + {error, Else} + end. + + +ms_mib_of(suite) -> []; +ms_mib_of(Config) when list(Config) -> + p("ms_mib_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance, + 'SNMP-USER-BASED-SM-MIB'), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +mib_of(Oid, ExpectedMibName) -> + ?DBG("mib_of -> entry with" + "~n Oid: ~p" + "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]), + %% case snmpa:mib_of(Oid) of + MibOf = snmpa:mib_of(Oid), + ?DBG("mib_of -> MibOf: ~n~p", [MibOf]), + case MibOf of + {ok, ExpectedMibName} -> + ok; + {ok, OtherMibName} -> + {error, {invalid_mib, ExpectedMibName, OtherMibName}}; + {error, Reason} -> + {error, Reason}; + Else -> + ?DBG("mib_of -> Else: ~n~p", [Else]), + {error, Else} + end. + + +app_info(suite) -> []; +app_info(Config) when list(Config) -> + SnmpDir = app_dir(snmp), + SslDir = app_dir(ssl), + CryptoDir = app_dir(crypto), + Attr = snmp:module_info(attributes), + AppVsn = + case lists:keysearch(app_vsn, 1, Attr) of + {value, {app_vsn, V}} -> + V; + false -> + "undefined" + end, + io:format("Root dir: ~s~n" + "SNMP: Application dir: ~s~n" + " Application ver: ~s~n" + "SSL: Application dir: ~s~n" + "CRYPTO: Application dir: ~s~n", + [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]), + ok. + +app_dir(App) -> + case code:lib_dir(App) of + D when list(D) -> + filename:basename(D); + {error, _Reason} -> + "undefined" + end. + + +test_v1(suite) -> {req, [], {conf, init_v1, v1_cases(), finish_v1}}. + +%v1_cases() -> [loop_mib]; +v1_cases() -> + [simple, + db_notify_client, + v1_processing, big, big2, loop_mib, + api, subagent, mnesia, multiple_reqs, + sa_register, v1_trap, sa_error, next_across_sa, undo, reported_bugs, + standard_mibs, sparse_table, cnt_64, + opaque, + % opaque]. + + change_target_addr_config]. + +init_v1(Config) when list(Config) -> + ?line SaNode = ?config(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v1} | start_v1_agent(Config)]. + +finish_v1(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v2(suite) -> {req, [], {conf, init_v2, v2_cases(), finish_v2}}. + +%v2_cases() -> [loop_mib_2]; +v2_cases() -> + [simple_2, v2_processing, big_2, big2_2, loop_mib_2, + api_2, subagent_2, mnesia_2, + multiple_reqs_2, sa_register_2, v2_trap, v2_inform, sa_error_2, + next_across_sa_2, undo_2, reported_bugs_2, standard_mibs_2, + v2_types, implied, sparse_table_2, cnt_64_2, opaque_2, v2_caps]. + +init_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_v2_agent(Config)]. + +finish_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v1_v2(suite) -> {req, [], {conf, init_v1_v2, v1_v2_cases(), finish_v1_v2}}. + +v1_v2_cases() -> + [simple_bi]. + +init_v1_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, bilingual} | start_bilingual_agent(Config)]. + +finish_v1_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v3(suite) -> {req, [], {conf, init_v3, v3_cases(), finish_v3}}. + +%v3_cases() -> [loop_mib_3]; +v3_cases() -> + [simple_3, v3_processing, + big_3, big2_3, api_3, subagent_3, mnesia_3, loop_mib_3, + multiple_reqs_3, sa_register_3, v3_trap, v3_inform, sa_error_3, + next_across_sa_3, undo_3, reported_bugs_3, standard_mibs_3, + v3_security, + v2_types_3, implied_3, sparse_table_3, cnt_64_3, opaque_3, v2_caps_3]. + +init_v3(Config) when list(Config) -> + %% Make sure crypto works, otherwise start_agent will fail + %% and we will be stuck with a bunch of mnesia tables for + %% the rest of this suite... + ?DBG("start_agent -> start crypto app",[]), + case os:type() of + vxworks -> + no_crypto; + _ -> + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end + end, + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v3], MgrDir, AgentDir, + tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_v3_agent(Config)]. + +finish_v3(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_multi_threaded(suite) -> {req, [], {conf, init_mt, mt_cases(), finish_mt}}. + +mt_cases() -> + [multi_threaded, mt_trap]. + +init_mt(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_multi_threaded_agent(Config)]. + +finish_mt(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +%% This one *must* be run first in each case. +init_case(Config) when list(Config) -> + ?DBG("init_case -> entry with" + "~n Config: ~p", [Config]), + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + MasterNode = node(), + + SaHost = ?HOSTNAME(SaNode), + MgrHost = ?HOSTNAME(MgrNode), + MasterHost = ?HOSTNAME(MasterNode), + {ok, MasterIP} = snmp_misc:ip(MasterHost), + {ok, MIP} = snmp_misc:ip(MgrHost), + {ok, SIP} = snmp_misc:ip(SaHost), + + + put(mgr_node, MgrNode), + put(sa_node, SaNode), + put(master_node, MasterNode), + put(sa_host, SaHost), + put(mgr_host, MgrHost), + put(master_host, MasterHost), + put(mip, tuple_to_list(MIP)), + put(masterip , tuple_to_list(MasterIP)), + put(sip, tuple_to_list(SIP)), + + MibDir = ?config(mib_dir, Config), + put(mib_dir, MibDir), + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + put(std_mib_dir, StdM), + + MgrDir = ?config(mgr_dir, Config), + put(mgr_dir, MgrDir), + + put(vsn, ?config(vsn, Config)), + ?DBG("init_case -> exit with" + "~n MasterNode: ~p" + "~n SaNode: ~p" + "~n MgrNode: ~p" + "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]), + {SaNode, MgrNode, MibDir}. + +load_master(Mib) -> + ?DBG("load_master -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]). + +load_master_std(Mib) -> + ?DBG("load_master_std -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]). + +unload_master(Mib) -> + ?DBG("unload_master -> entry with" + "~n Mib: ~p", [Mib]), + ok = snmpa:unload_mibs(snmp_master_agent, [Mib]). + +loaded_mibs() -> + ?DBG("loaded_mibs -> entry",[]), + Info = snmpa:info(snmp_master_agent), + {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info), + [atom_to_list(Mib) || {Mib,_,_} <- Mibs]. + +unload_mibs(Mibs) -> + ?DBG("unload_mibs -> entry with" + "~n Mibs: ~p", [Mibs]), + ok = snmpa:unload_mibs(snmp_master_agent, Mibs). + +start_subagent(SaNode, RegTree, Mib) -> + ?DBG("start_subagent -> entry with" + "~n SaNode: ~p" + "~n RegTree: ~p" + "~n Mib: ~p", [SaNode, RegTree, Mib]), + MA = whereis(snmp_master_agent), + ?DBG("start_subagent -> MA: ~p", [MA]), + MibDir = get(mib_dir), + Mib1 = join(MibDir,Mib), + %% BMK BMK +% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of + case rpc:call(SaNode, snmpa_supervisor, + start_sub_agent, [MA, RegTree, [Mib1]]) of + {ok, SA} -> + ?DBG("start_subagent -> SA: ~p", [SA]), + {ok, SA}; + Error -> + ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]}) + end. + +stop_subagent(SA) -> + ?DBG("stop_subagent -> entry with" + "~n SA: ~p", [SA]), + %% BNK BMK + %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]). + rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]). + +%%----------------------------------------------------------------- +%% This function takes care of the old OTP-SNMPEA-MIB. +%% Unfortunately, the testcases were written to use the data in the +%% internal tables, and these table are now obsolete and not used +%% by the agent. Therefore, we emulate them by using +%% OLD-SNMPEA-MIB, which uses the default impl. of all tables. +%% +%% These two rows must exist in intCommunityTable +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. +%% (But with the manager's IP address) +%% +%%----------------------------------------------------------------- +init_old() -> + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [6 | "public"], + {get(mip), "public", 2, 2}), + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [13 | "standard trap"], + {get(mip), "standard trap", 2, 1}), + snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]). + + + +simple(suite) -> []; +simple(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(simple_standard_test). + +simple_2(X) -> simple(X). + +simple_bi(suite) -> []; +simple_bi(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(vsn, v1), % First, try v1 manager + try_test(simple_standard_test), + + put(vsn, v2), % Then, try v2 manager + try_test(simple_standard_test). + +simple_3(X) -> + simple(X). + +big(suite) -> []; +big(Config) when list(Config) -> + ?DBG("big -> entry", []), + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?DBG("big -> SA: ~p", [SA]), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB"). + +big_2(X) -> big(X). + +big_3(X) -> big(X). + + +big2(suite) -> []; +big2(Config) when list(Config) -> + %% This is exactly the same tests as 'big', but with the + %% v2 equivalent of the mibs. + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"), + ?line load_master("OLD-SNMPEA-MIB-v2"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB-v2"). + +big2_2(X) -> big2(X). + +big2_3(X) -> big2(X). + + +multi_threaded(suite) -> []; +multi_threaded(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(multi_threaded_test), + ?line unload_master("Test1"). + +mt_trap(suite) -> []; +mt_trap(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + ?line load_master("TestTrapv2"), + try_test(mt_trap_test, [MA]), + ?line unload_master("TestTrapv2"), + ?line unload_master("Test1"). + +v2_types(suite) -> []; +v2_types(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(types_v2_test), + ?line unload_master("Test1"). + +v2_types_3(X) -> v2_types(X). + + +implied(suite) -> []; +implied(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(implied_test,[MA]), + ?line unload_master("Test1"). + +implied_3(X) -> implied(X). + + +sparse_table(suite) -> []; +sparse_table(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(sparse_table_test), + ?line unload_master("Test1"). + +sparse_table_2(X) -> sparse_table(X). + +sparse_table_3(X) -> sparse_table(X). + +cnt_64(suite) -> []; +cnt_64(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(cnt_64_test, [MA]), + ?line unload_master("Test1"). + +cnt_64_2(X) -> cnt_64(X). + +cnt_64_3(X) -> cnt_64(X). + +opaque(suite) -> []; +opaque(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(opaque_test), + ?line unload_master("Test1"). + +opaque_2(X) -> opaque(X). + +opaque_3(X) -> opaque(X). + + +change_target_addr_config(suite) -> []; +change_target_addr_config(Config) when list(Config) -> + p("Testing changing target address config..."), + ?LOG("change_target_addr_config -> entry",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(sname,snmp_suite), + put(verbosity,trace), + + MA = whereis(snmp_master_agent), + + ?LOG("change_target_addr_config -> load TestTrap",[]), + ?line load_master("TestTrap"), + + ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,trace), + + %% First send some traps that will arive att the original manager + ?LOG("change_target_addr_config -> send trap",[]), + try_test(ma_trap1, [MA]), + + ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,silence), + + %% Start new dummy listener + ?LOG("change_target_addr_config -> start dummy manager",[]), + ?line {ok,Pid,NewPort} = dummy_manager_start(MA), + + %% Reconfigure + ?LOG("change_target_addr_config -> reconfigure",[]), + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_addr_conf(AgentDir, NewPort), + ?line snmp_target_mib:reconfigure(AgentDir), + + %% Send the trap again + ?LOG("change_target_addr_config -> send trap again",[]), + catch dummy_manager_send_trap2(Pid), + + ?LOG("change_target_addr_config -> await trap ack",[]), + catch dummy_manager_await_trap2_ack(), + + ?LOG("change_target_addr_config -> stop dummy manager",[]), + ?line ok = dummy_manager_stop(Pid), + + ?LOG("change_target_addr_config -> reset target address config",[]), + ?line reset_target_addr_conf(AgentDir), + + ?LOG("change_target_addr_config -> unload TestTrap",[]), + ?line unload_master("TestTrap"). + + +dummy_manager_start(MA) -> + ?DBG("dummy_manager_start -> entry",[]), + Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]), + ?DBG("dummy_manager_start -> Pid: ~p",[Pid]), + await_dummy_manager_started(Pid). + +await_dummy_manager_started(Pid) -> + receive + {dummy_manager_started,Pid,Port} -> + ?DBG("dummy_manager_start -> acknowledge received with" + "~n Port: ~p",[Port]), + {ok,Pid,Port}; + {'EXIT', Pid, Reason} -> + {error, Pid, Reason}; + O -> + ?LOG("dummy_manager_start -> received unknown message:" + "~n ~p",[O]), + await_dummy_manager_started(Pid) + end. + +dummy_manager_stop(Pid) -> + ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]), + Pid ! stop, + receive + {dummy_manager_stopping, Pid} -> + ?DBG("dummy_manager_stop -> acknowledge received",[]), + ok + after 10000 -> + ?ERR("dummy_manager_stop -> timeout",[]), + timeout + end. + +dummy_manager_send_trap2(Pid) -> + ?DBG("dummy_manager_send_trap2 -> entry",[]), + Pid ! {send_trap,testTrap2}. + +dummy_manager_await_trap2_ack() -> + ?DBG("dummy_manager_await_trap2 -> entry",[]), + receive + {received_trap,Trap} -> + ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]), + %% Note: + %% Without this sleep the v2_inform_i testcase failes! There + %% is no relation between these two test cases as far as I + %% able to figure out... + sleep(60000), + ok; + O -> + ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]), + ok + after 10000 -> + ?ERR("dummy_manager_await_trap2 -> timeout",[]), + timeout + end. + +dummy_manager_init(Parent,MA) -> + ?DBG("dummy_manager_init -> entry with" + "~n Parent: ~p" + "~n MA: ~p",[Parent,MA]), + {ok,S} = gen_udp:open(0,[{recbuf,65535}]), + ?DBG("dummy_manager_init -> S: ~p",[S]), + {ok,Port} = inet:port(S), + ?DBG("dummy_manager_init -> Port: ~p",[Port]), + Parent ! {dummy_manager_started,self(),Port}, + dummy_manager_loop(Parent,S,MA). + +dummy_manager_loop(P,S,MA) -> + ?LOG("dummy_manager_loop -> ready for receive",[]), + receive + {send_trap,Trap} -> + ?LOG("dummy_manager_loop -> received trap send request" + "~n Trap: ~p",[Trap]), + snmpa:send_trap(MA, Trap, "standard trap"), + dummy_manager_loop(P,S,MA); + {udp, _UdpId, Ip, UdpPort, Bytes} -> + ?LOG("dummy_manager_loop -> received upd message" + "~n from: ~p:~p" + "~n size: ~p", + [Ip, UdpPort, dummy_manager_message_sz(Bytes)]), + R = dummy_manager_handle_message(Bytes), + ?DBG("dummy_manager_loop -> R: ~p",[R]), + P ! R, + dummy_manager_loop(P,S,MA); + stop -> + ?DBG("dummy_manager_loop -> received stop request",[]), + P ! {dummy_manager_stopping, self()}, + gen_udp:close(S), + exit(normal); + O -> + ?LOG("dummy_manager_loop -> received unknown message:" + "~n ~p",[O]), + dummy_manager_loop(P,S,MA) + end. + +dummy_manager_message_sz(B) when binary(B) -> + size(B); +dummy_manager_message_sz(L) when list(L) -> + length(L); +dummy_manager_message_sz(_) -> + undefined. + +dummy_manager_handle_message(Bytes) -> + case (catch snmp_pdus:dec_message(Bytes)) of + {'EXIT',Reason} -> + ?ERR("dummy_manager_handle_message -> " + "failed decoding message only:~n ~p",[Reason]), + {error,Reason}; + M -> + ?DBG("dummy_manager_handle_message -> decoded message:" + "~n ~p",[M]), + {received_trap,M} + end. + + +api(suite) -> []; +api(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(api_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +api_2(X) -> api(X). + +api_3(X) -> api(X). + + +subagent(suite) -> []; +subagent(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + try_test(load_test_sa), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + + p("Loading previous subagent mib in master and testing..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]), + try_test(load_test), + + p("Unloading previous subagent mib in master and testing..."), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]), + try_test(unreg_test), + p("Testing register subagent..."), + rpc:call(SaNode, snmp, register_subagent, + [MA, ?klas1, SA]), + try_test(load_test_sa), + + ?line stop_subagent(SA), + try_test(unreg_test). + +subagent_2(X) -> subagent(X). + +subagent_3(X) -> subagent(X). + + +mnesia(suite) -> []; +mnesia(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent with mnesia impl..."), + {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + try_test(big_test_2), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA). + +mnesia_2(X) -> mnesia(X). + +mnesia_3(X) -> mnesia(X). + + +multiple_reqs(suite) -> + {req, [], {conf, init_mul, mul_cases(), finish_mul}}. + +mul_cases() -> + [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err]. + +multiple_reqs_2(suite) -> + {req, [], {conf, init_mul, mul_cases_2(), finish_mul}}. + +multiple_reqs_3(_X) -> + {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}. + + +mul_cases_2() -> + [mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2, mul_set_err_2]. + + +mul_cases_3() -> + [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3]. + + +init_mul(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + [{mul_sub, SA} | Config]. + +finish_mul(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + SA = ?config(mul_sub, Config), + + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA), + lists:keydelete(mul_sub, 1, Config). + +mul_get(suite) -> []; +mul_get(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get..."), + try_test(do_mul_get). + +mul_get_2(X) -> mul_get(X). + +mul_get_3(X) -> mul_get(X). + + +mul_get_err(suite) -> []; +mul_get_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get with error..."), + try_test(do_mul_get_err). + +mul_get_err_2(X) -> mul_get_err(X). + +mul_get_err_3(X) -> mul_get_err(X). + + +mul_next(suite) -> []; +mul_next(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next). + +mul_next_2(X) -> mul_next(X). + +mul_next_3(X) -> mul_next(X). + + +mul_next_err(suite) -> []; +mul_next_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next_err). + +mul_next_err_2(X) -> mul_next_err(X). + +mul_next_err_3(X) -> mul_next_err(X). + + +mul_set(suite) -> []; +mul_set(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set..."), + try_test(do_mul_set). + +mul_set_2(X) -> mul_set(X). + +mul_set_3(X) -> mul_set(X). + + +mul_set_err(suite) -> []; +mul_set_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set with error..."), + try_test(do_mul_set_err). + +mul_set_err_2(X) -> mul_set_err(X). + +mul_set_err_3(X) -> mul_set_err(X). + + +sa_register(suite) -> []; +sa_register(Config) when list(Config) -> + ?DBG("sa_register -> entry", []), + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?DBG("sa_register -> start subagent", []), + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + + ?DBG("sa_register -> unregister subagent", []), + p("Testing unregister subagent (2)..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Loading SA-MIB..."), + ?DBG("sa_register -> unload mibs", []), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + ?DBG("sa_register -> unload mibs", []), + snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]), + ?DBG("sa_register -> register subagent", []), + rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]), + try_test(sa_mib), + + ?DBG("sa_register -> stop subagent", []), + ?line stop_subagent(SA). + +sa_register_2(X) -> sa_register(X). + +sa_register_3(X) -> sa_register(X). + + +v1_trap(suite) -> []; +v1_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_trap1, [MA]), + try_test(ma_trap2, [MA]), + try_test(ma_v2_2_v1_trap, [MA]), + try_test(ma_v2_2_v1_trap2, [MA]), + + p("Testing trap sending from subagent..."), + try_test(sa_trap1, [SA]), + try_test(sa_trap2, [SA]), + try_test(sa_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v2_trap(suite) -> []; +v2_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + + try_test(ma_v2_trap1, [MA]), + try_test(ma_v2_trap2, [MA]), + try_test(ma_v1_2_v2_trap, [MA]), + try_test(ma_v1_2_v2_trap2, [MA]), + + try_test(sa_mib), + p("Testing trap sending from subagent..."), + try_test(sa_v1_2_v2_trap1, [SA]), + try_test(sa_v1_2_v2_trap2, [SA]), + try_test(sa_v1_2_v2_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v3_trap(X) -> + v2_trap(X). + +v2_inform(suite) -> + {req, [], {conf, init_v2_inform, [v2_inform_i], finish_v2_inform}}. + +v3_inform(_X) -> + %% v2_inform(X). + {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}. + +init_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +init_v3_inform(X) -> + init_v2_inform(X). + +finish_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +finish_v3_inform(X) -> + finish_v2_inform(X). + + + +v2_inform_i(suite) -> []; +v2_inform_i(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing inform sending from master agent... NOTE! This test\ntakes a " + "few minutes (5) to complete."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_v2_inform1, [MA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"). + +v3_inform_i(X) -> v2_inform_i(X). + + +sa_error(suite) -> []; +sa_error(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing sa bad value (is_set_ok)..."), + try_test(sa_errs_bad_value), + + p("Testing sa gen err (set)..."), + try_test(sa_errs_gen_err), + + p("Testing too big..."), + try_test(sa_too_big), + + ?line unload_master("OLD-SNMPEA-MIB"), + stop_subagent(SA). + +sa_error_2(X) -> sa_error(X). + +sa_error_3(X) -> sa_error(X). + + +next_across_sa(suite) -> []; +next_across_sa(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Loading another subagent mib..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]), + + rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]), + try_test(load_test_sa), + + p("Testing next across subagent (endOfMibView from SA)..."), + try_test(next_across_sa), + + p("Unloading mib"), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Starting another subagent"), + ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"), + p("Testing next across subagent (wrong prefix from SA)..."), + try_test(next_across_sa), + + stop_subagent(SA), + stop_subagent(SA2). + +next_across_sa_2(X) -> next_across_sa(X). + +next_across_sa_3(X) -> next_across_sa(X). + + +undo(suite) -> []; +undo(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing undo phase at master agent..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]), + try_test(undo_test), + try_test(api_test2), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]), + + p("Testing bad return values from instrum. funcs..."), + try_test(bad_return), + + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]), + + p("Testing undo phase at subagent..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]), + ?line ok = snmpa:register_subagent(MA, ?klas3, SA), + ?line ok = snmpa:register_subagent(MA, ?klas4, SA), + try_test(undo_test), + try_test(api_test3), + + p("Testing undo phase across master/subagents..."), + try_test(undo_test), + try_test(api_test3), + stop_subagent(SA). + +undo_2(X) -> undo(X). + +undo_3(X) -> undo(X). + +%% Req. Test2 +v1_processing(suite) -> []; +v1_processing(Config) when list(Config) -> + ?DBG("v1_processing -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v1_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v2_processing(suite) -> []; +v2_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v3_processing(suite) -> []; +v3_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), % same as v2! + ?line unload_master("Test2"). + + +%% We'll try get/set/trap and inform for all the auth & priv protocols. +%% For informs, the mgr is auth-engine. The agent has to sync. This is +%% accomplished by the first inform sent. That one will generate a +%% report, which makes it in sync. The notification-generating +%% application times out, and send again. This time it'll work. +v3_security(suite) -> [v3_crypto_basic, v3_md5_auth, v3_sha_auth, v3_des_priv]. + +v3_crypto_basic(suite) -> []; +v3_crypto_basic(_Config) -> + EID = [0,0,0,0,0,0,0,0,0,0,0,2], + %% From rfc2274 appendix A.3.1 + ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID), + ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f, + 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] = + KMd5_1, + %% From rfc2274 appendix A.3.2 + ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID), + ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23, + 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] = + KSHA_1, + %% From rfc2274, appendix A.5.1 + ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9, + 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] = + snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + %% From rfc2274, appendix A.5.2 + ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4, + 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db, + 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + KSHA_1t = lists:sublist(KSHA_1, 16), + KSHA_2t = lists:sublist(KSHA_2, 16), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b, + 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + + %% Try with correct random + ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2), + ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1), + ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2), + ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2), + ok. + + + +v3_md5_auth(suite) -> []; +v3_md5_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing MD5 authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authMD5"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_sha_auth(suite) -> []; +v3_sha_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing SHA authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authSHA"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_des_priv(suite) -> []; +v3_des_priv(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing DES encryption...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +%% Make sure mgr is in sync with agent +v3_sync(Funcs) -> + ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]), + g([[sysDescr, 0]]), + expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]), + g([[sysDescr, 0]]), + expect(433, [{[sysDescr,0], any}]), + lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs). + +v3_inform_sync(MA) -> + ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, + "standard inform", []), + %% Make sure agent is in sync with mgr... + ?DBG("v3_sync -> wait some time: ",[]), + sleep(20000), % more than 1500*10 in target_addr.conf + ?DBG("v3_sync -> await response",[]), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]). + + +v2_caps(suite) -> []; +v2_caps(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(v2_caps_i, [node()]). + +v2_caps_3(X) -> v2_caps(X). + + +v2_caps_i(Node) -> + ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]), + g([[sysORID, Idx], [sysORDescr, Idx]]), + ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]}, + {[sysORDescr, Idx], "test cap"}]), + ?line rpc:call(Node, snmp, del_agent_caps, [Idx]), + g([[sysORID, Idx]]), + ?line expect(2, [{[sysORID, Idx], noSuchInstance}]). + + +%% Req. Test2 +v1_proc() -> + ?DBG("v1_proc -> entry", []), + %% According to RFC1157. + %% Template: <Section>:<list no> + v1_get_p(), + v1_get_next_p(), + v1_set_p(). + + +v1_get_p() -> + %% 4.1.2:1 + g([[test2]]), + ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]), + g([[tDescr]]), + ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]), + g([[tDescr2,0]]), + ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]), + g([[tDescr3,0]]), + ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]), + g([[tDescr4,0]]), + ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'}, + {[tDescr,0], 'NULL'}]), + g([[sysDescr,3]]), + ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]), + + %% 4.1.2:2 + g([[tTable]]), + ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]), + g([[tEntry]]), + ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]), + + %% 4.1.2:3 + g([[tTooBig, 0]]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.2:4 + g([[tGenErr1, 0]]), + ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]). + + +v1_get_next_p() -> + %% 4.1.3:1 + gn([[1,3,7,1]]), + ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]), + gn([[tDescr2]]), + ?line expect(11, tooBig, 0, any), + + %% 4.1.3:2 + gn([[tTooBig]]), + io:format("We currently don't handle tooBig correct!!!\n"), +% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]), + ?line expect(20, tooBig, 0, any), + + %% 4.1.3:3 + gn([[tGenErr1]]), +% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]), + ?line expect(40, genErr, 1, any), + gn([[tGenErr2]]), +% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]), + ?line expect(41, genErr, 1, any), + gn([[sysDescr], [tGenErr3]]), +% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'}, +% {[tGenErr3], 'NULL'}]). + ?line expect(42, genErr, 2, any). + +v1_set_p() -> + %% 4.1.5:1 + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]), + s([{[tDescr3], s, "noSuchObject"}]), + ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]), + s([{[tDescr3,1], s, "noSuchInstance"}]), + ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]), + s([{[tDescr2,0], s, "inconsistentName"}]), + ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]), + + %% 4.1.5:2 + s([{[tDescr2, 0], i, 4}]), + ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.1.5:3 + %% The standard is quite incorrect here. The resp pdu was too big. In + %% the resp pdu, we have the original vbs. In the tooBig pdu we still + %% have to original vbs => the tooBig pdu is too big as well!!! It + %% may not get it to the manager, unless the agent uses 'NULL' instead + %% of the std-like original value. + s([{[tTooBig, 0], s, ?tooBigStr}]), + %% according to std: +% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.5:4 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]), + s([{[tDescr2, 0], s, "commit_fail"}]), + ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]). + +%% Req. Test2 +v2_proc() -> + %% According to RFC1905. + %% Template: <Section>:<list no> + ?DBG("v2_proc -> entry",[]), + v2_get_p(), + v2_get_next_p(), + v2_get_bulk_p(), + v2_set_p(). + +v2_get_p() -> + %% 4.2.1:2 + ?DBG("v2_get_p -> entry",[]), + g([[test2]]), + ?line expect(10, [{[test2], noSuchObject}]), + g([[tDescr]]), + ?line expect(11, [{[tDescr], noSuchObject}]), + g([[tDescr4,0]]), + ?line expect(12, [{[tDescr4,0], noSuchObject}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}, + {[tDescr,0], noSuchObject}]), + g([[tTable]]), + ?line expect(14, [{[tTable], noSuchObject}]), + g([[tEntry]]), + ?line expect(15, [{[tEntry], noSuchObject}]), + + %% 4.2.1:3 + g([[tDescr2,0]]), %% instrum ret noSuchName!!! + ?line expect(20, [{[tDescr2,0], noSuchInstance}]), + g([[tDescr3,0]]), + ?line expect(21, [{[tDescr3,0], noSuchInstance}]), + g([[sysDescr,3]]), + ?line expect(22, [{[sysDescr, 3], noSuchInstance}]), + g([[tIndex,1]]), + ?line expect(23, [{[tIndex, 1], noSuchInstance}]), + + %% 4.2.1 - any other error: genErr + g([[tGenErr1, 0]]), + ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]), + + %% 4.2.1 - tooBig + g([[tTooBig, 0]]), + ?line expect(40, tooBig, 0, []). + + +v2_get_next_p() -> + %% 4.2.2:2 + ?DBG("v2_get_next_p -> entry",[]), + gn([[1,3,7,1]]), + ?line expect(10, [{[1,3,7,1], endOfMibView}]), + gn([[sysDescr], [1,3,7,1]]), + ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gn([[tCnt2, 1]]), + ?line expect(12, [{[tCnt2,2], 100}]), + gn([[tCnt2, 2]]), + ?line expect(12, [{[tCnt2,2], endOfMibView}]), + + %% 4.2.2 - any other error: genErr + gn([[tGenErr1]]), + ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]), + gn([[tGenErr2]]), + ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]), + gn([[sysDescr], [tGenErr3]]), + ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'}, + {[tGenErr3], 'NULL'}]), + + %% 4.2.2 - tooBig + gn([[tTooBig]]), + ?line expect(20, tooBig, 0, []). + +v2_get_bulk_p() -> + %% 4.2.3 + ?DBG("v2_get_bulk_p -> entry",[]), + gb(1, 1, []), + ?line expect(10, []), + gb(-1, 1, []), + ?line expect(11, []), + gb(-1, -1, []), + ?line expect(12, []), + gb(-1, -1, []), + ?line expect(13, []), + gb(2, 0, [[sysDescr], [1,3,7,1]]), + ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(1, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(0, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]), + ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]), + ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[sysDescr, 0], "Erlang SNMP agent"}]), + + gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig. + ?line expect(19, []), + + gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]), + ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'}, + {[sysObjectID], 'NULL'}, + {[tGenErr1], 'NULL'}, + {[sysDescr], 'NULL'}]), + gb(0, 2, [[tCnt2, 1]]), + ?line expect(21, [{[tCnt2,2], 100}, + {[tCnt2,2], endOfMibView}]). + + +v2_set_p() -> + %% 4.2.5:1 + ?DBG("v2_set_p -> entry",[]), + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]), + + %% 4.2.5:2 + s([{[1,3,6,1,0], s, "noSuchObject"}]), + ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]), + + %% 4.2.5:3 + s([{[tDescr2, 0], i, 4}]), + ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.2.5:4 + s([{[tStr, 0], s, ""}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]), + s([{[tStr, 0], s, "12345"}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]), + + %% 4.2.5:5 - N/A + + %% 4.2.5:6 + s([{[tInt1, 0], i, 0}]), + ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]), + s([{[tInt1, 0], i, 5}]), + ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]), + s([{[tInt2, 0], i, 0}]), + ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]), + s([{[tInt2, 0], i, 5}]), + ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]), + s([{[tInt3, 0], i, 5}]), + ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]), + + %% 4.2.5:7 + s([{[tDescrX, 1, 1], s, "noCreation"}]), + ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]), + + %% 4.2.5:8 + s([{[tDescrX, 1, 2], s, "inconsistentName"}]), + ?line expect(80, inconsistentName, 1, + [{[tDescrX, 1, 2], "inconsistentName"}]), + + %% 4.2.5:9 + s([{[tCnt, 1, 2], i, 5}]), + ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]), + + %% 4.2.5:10 + s([{[tDescr2,0], s, "inconsistentValue"}]), + ?line expect(100, inconsistentValue, 1, + [{[tDescr2,0], "inconsistentValue"}]), + + %% 4.2.5:11 + s([{[tDescr2,0], s, "resourceUnavailable"}]), + ?line expect(110, resourceUnavailable, 1, + [{[tDescr2,0],"resourceUnavailable"}]), + + %% 4.2.5:12 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]). + + %% commitFailed and undoFailed is tested by the 'undo' case. + + +%% Req. OLD-SNMPEA-MIB +table_test() -> + io:format("Testing simple get, next and set on communityTable...~n"), +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. + Key1c3 = [intCommunityViewIndex,get(mip),is("public")], + Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")], + Key1c4 = [intCommunityAccess,get(mip),is("public")], + EndKey = [intCommunityEntry,[9],get(mip),is("public")], + gn([[intCommunityEntry]]), + ?line expect(7, [{Key1c3, 2}]), + gn([[intCommunityTable]]), + ?line expect(71, [{Key1c3, 2}]), + gn([[community]]), + ?line expect(72, [{Key1c3, 2}]), + gn([[otpSnmpeaMIB]]), + ?line expect(73, [{Key1c3, 2}]), + gn([[ericsson]]), + ?line expect(74, [{Key1c3, 2}]), + gn([Key1c3]), + ?line expect(8, [{Key2c3, 2}]), + gn([Key2c3]), + ?line expect(9, [{Key1c4, 2}]), + gn([EndKey]), + AgentIp = [intAgentIpAddress,0], + ?line expect(10, [{AgentIp, any}]), + g([Key1c3]), + ?line expect(11, [{Key1c3, 2}]), + g([EndKey]), + ?line ?v1_2(expect(12, noSuchName, 1, any), + expect(12, [{EndKey, noSuchObject}])), + + io:format("Testing row creation/deletion on communityTable...~n"), + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + s([{NewKeyc5, ?createAndGo}]), + ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any), + s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]), + ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]), + g([NewKeyc4]), + ?line expect(16, [{NewKeyc4, 2}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(17, [{NewKeyc5, ?destroy}]), + s([{NewKeyc4, 2}]), + ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]), + s([{NewKeyc5, ?createAndWait}]), + ?line expect(19, [{NewKeyc5, ?createAndWait}]), + g([NewKeyc5]), + ?line expect(20, [{NewKeyc5, ?notReady}]), + s([{NewKeyc4, 2}]), + ?line expect(21, [{NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(22, [{NewKeyc5, ?notReady}]), + s([{NewKeyc3, 2}]), + ?line expect(23, [{NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(24, [{NewKeyc5, ?notInService}]), + s([{NewKeyc5, ?active}]), + ?line expect(25, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(26, [{NewKeyc5, ?destroy}]), + s([{NewKeyc3, 3}]), + ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]), + otp_1128(). + +%% Req. system group +simple_standard_test() -> + ?DBG("simple_standard_test -> entry",[]), + gn([[1,1]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3]]), + ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6]]), + ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1]]), + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2]]), + ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1]]), + ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1,1]]), + ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[sysDescr]]), + ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr,0]]), + ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr]]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{[sysDescr], noSuchObject}])), + g([[1,6,7,0]]), + ?line ?v1_2(expect(41, noSuchName, 1, any), + expect(3, [{[1,6,7,0], noSuchObject}])), + gn([[1,13]]), + ?line ?v1_2(expect(4, noSuchName,1, any), + expect(4, [{[1,13], endOfMibView}])), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + g([[sysLocation, 0]]), + ?line expect(6, [{[sysLocation, 0], "new_value"}]), + io:format("Testing noSuchName and badValue...~n"), + s([{[sysServices,0], 3}]), + ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any), + s([{[sysLocation, 0], i, 3}]), + ?line expect(62, ?v1_2(badValue, wrongType), 1, any), + ?DBG("simple_standard_test -> done",[]), + ok. + +%% This is run in the agent node +db_notify_client(suite) -> []; +db_notify_client(Config) when list(Config) -> + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p", + [SaNode,MgrNode,MibDir]), + snmpa_local_db:register_notify_client(self(),?MODULE), + + %% This call (the manager) will issue to set operations, so + %% we expect to receive to notify(insert) calls. + try_test(db_notify_client_test), + + ?DBG("await first notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok + end, + + ?DBG("await second notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok + end, + + snmpa_local_db:unregister_notify_client(self()). + + +%% This is run in the manager node +db_notify_client_test() -> + ?DBG("set first new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + + ?DBG("set second new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]). + +notify(Pid,What) -> + ?DBG("notify(~p,~p) -> called",[Pid,What]), + Pid ! {db_notify_test_reply,What}. + + +%% Req: system group, OLD-SNMPEA-MIB, Klas1 +big_test() -> + ?DBG("big_test -> testing simple next/get/set @ master agent...",[]), + simple_standard_test(), + + ?DBG("big_test -> testing simple next/get/set @ subagent...",[]), + gn([[klas1]]), + ?line expect(1, [{[fname,0], ""}]), + g([[fname,0]]), + ?line expect(2, [{[fname,0], ""}]), + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[fname,0]]), + ?line expect(4, [{[fname,0], "test set"}]), + + ?DBG("big_test -> " + "testing next from last instance in master to subagent...",[]), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname,0], "test set"}]), + s([{[fname,0], s, ""}]), + ?line expect(52, [{[fname,0], ""}]), + + table_test(), + + ?DBG("big_test -> adding one row in subagent table",[]), + _FTab = [friendsEntry], + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {[friendsEntry, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [friendsEntry, [3, 3]]]), + ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?active}]), + s([{[friendsEntry, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]), + + otp_1131(), + + ?DBG("big_test -> adding two rows in subagent table with special INDEX", + []), + s([{[kompissEntry, [1, 3]], s, "kompis3"}, + {[kompissEntry, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?createAndGo}]), + g([[kompissEntry, [1, 3]], + [kompissEntry, [2, 3]]]), + ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + gn([[kompissEntry, [1]], + [kompissEntry, [2]]]), + ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + s([{[kompissEntry, [1, 2]], s, "kompis3"}, + {[kompissEntry, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?createAndGo}]), + gn([[kompissEntry, [1, 1]], + [kompissEntry, [2, 1]]]), + ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?active}]), + s([{[kompissEntry, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]), + s([{[kompissEntry, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]), + ?DBG("big_test -> done",[]), + ok. + +%% Req. system group, Klas2, OLD-SNMPEA-MIB +big_test_2() -> + p("Testing simple next/get/set @ master agent (2)..."), + simple_standard_test(), + + p("Testing simple next/get/set @ subagent (2)..."), + gn([[klas2]]), + ?line expect(1, [{[fname2,0], ""}]), + g([[fname2,0]]), + ?line expect(2, [{[fname2,0], ""}]), + s([{[fname2,0], s, "test set"}]), + ?line expect(3, [{[fname2,0], "test set"}]), + g([[fname2,0]]), + ?line expect(4, [{[fname2,0], "test set"}]), + + otp_1298(), + + p("Testing next from last object in master to subagent (2)..."), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname2,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname2,0], "test set"}]), + + table_test(), + + p("Adding one row in subagent table (2)"), + _FTab = [friendsEntry2], + s([{[friendsEntry2, [2, 3]], s, "kompis3"}, + {[friendsEntry2, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?createAndGo}]), + g([[friendsEntry2, [2, 3]], + [friendsEntry2, [3, 3]]]), + ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?active}]), + s([{[friendsEntry2, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]), + + p("Adding two rows in subagent table with special INDEX (2)"), + s([{[kompissEntry2, [1, 3]], s, "kompis3"}, + {[kompissEntry2, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?createAndGo}]), + g([[kompissEntry2, [1, 3]], + [kompissEntry2, [2, 3]]]), + ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + gn([[kompissEntry2, [1]], + [kompissEntry2, [2]]]), + ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + s([{[kompissEntry2, [1, 2]], s, "kompis3"}, + {[kompissEntry2, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?createAndGo}]), + gn([[kompissEntry2, [1, 1]], + [kompissEntry2, [2, 1]]]), + ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?active}]), + s([{[kompissEntry2, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]), + s([{[kompissEntry2, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]), + ok. + +%% Req. Test1 +multi_threaded_test() -> + p("Testing multi threaded agent..."), + g([[multiStr,0]]), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(1, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "pelle"}]), + ?line expect(2, [{[sysLocation, 0], "pelle"}]), + Pid ! continue, + ?line expect(3, [{[multiStr,0], "ok"}]), + + s([{[multiStr, 0], s, "block"}]), + Pid2 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(4, [{[sysUpTime,0], any}]), + g([[multiStr,0]]), + Pid3 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(5, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "kalle"}]), + Pid3 ! continue, + ?line expect(6, [{[multiStr,0], "ok"}]), + Pid2 ! continue, + ?line expect(7, [{[multiStr,0], "block"}]), + ?line expect(8, [{[sysLocation,0], "kalle"}]). + +%% Req. Test1, TestTrapv2 +mt_trap_test(MA) -> + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + snmpa:send_trap(MA, mtTrap, "standard trap"), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(2, [{[sysUpTime,0], any}]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + Pid ! continue, + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [2]}, + {[multiStr,0], "ok"}]). + + +get_multi_pid() -> + get_multi_pid(10). +get_multi_pid(0) -> + ?line ?FAIL(no_global_name); +get_multi_pid(N) -> + sleep(1000), + case global:whereis_name(snmp_multi_tester) of + Pid when pid(Pid) -> Pid; + _ -> get_multi_pid(N-1) + end. + +%% Req. Test1 +types_v2_test() -> + p("Testing v2 types..."), + + s([{[bits1,0], 2#10}]), + ?line expect(1, [{[bits1,0], ?str(2#10)}]), + g([[bits1,0]]), + ?line expect(2, [{[bits1,0], ?str(2#101)}]), + + s([{[bits2,0], 2#11000000110}]), + ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]), + g([[bits2,0]]), + ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]), + + g([[bits3,0]]), + ?line expect(50, genErr, 1, any), + + g([[bits4,0]]), + ?line expect(51, genErr, 1, any), + + s([{[bits1,0], s, [2#10]}]), + ?line expect(6, ?v1_2(badValue, wrongValue), 1, any), + + s([{[bits2,0], 2#11001001101010011}]), + ?line expect(7, ?v1_2(badValue, wrongValue), 1, any). + + +%% Req. Test1 +implied_test(MA) -> + ?LOG("implied_test -> start",[]), + p("Testing IMPLIED..."), + + snmpa:verbosity(MA,trace), + snmpa:verbosity(MA,trace), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = "apa", + Idx2 = "qq", + ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]), + ?line expect(1, [{[testStatus, Idx1], ?createAndGo}, + {[testDescr, Idx1], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]), + ?line expect(2, [{[testStatus, Idx2], ?createAndGo}, + {[testDescr, Idx2], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr)",[]), + gn([[testDescr]]), + ?line expect(3, [{[testDescr,Idx1], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr) of row 1",[]), + gn([[testDescr,Idx1]]), + ?line expect(4, [{[testDescr,Idx2], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?destroy}]), + ?line expect(5, [{[testStatus, Idx1], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?destroy}]), + ?line expect(6, [{[testStatus, Idx2], ?destroy}]), + + %% Try the same in other table + Idx3 = [1, "apa"], + Idx4 = [1, "qq"], + ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]), + ?line expect(1, [{[testStatus2, Idx3], ?createAndGo}, + {[testDescr2, Idx3], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]), + ?line expect(2, [{[testStatus2, Idx4], ?createAndGo}, + {[testDescr2, Idx4], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr2)",[]), + gn([[testDescr2]]), + ?line expect(3, [{[testDescr2,Idx3], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr2) of row 1",[]), + gn([[testDescr2,Idx3]]), + ?line expect(4, [{[testDescr2,Idx4], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?destroy}]), + ?line expect(5, [{[testStatus2, Idx3], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?destroy}]), + ?line expect(6, [{[testStatus2, Idx4], ?destroy}]), + + snmpa:verbosity(MA,log), + + ?LOG("implied_test -> done",[]). + + + +%% Req. Test1 +sparse_table_test() -> + p("Testing sparse table..."), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + s([{[sparseStatus, Idx1], i, ?createAndGo}, + {[sparseDescr, Idx1], s, "row 1"}]), + ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo}, + {[sparseDescr, Idx1], "row 1"}]), + s([{[sparseStatus, Idx2], i, ?createAndGo}, + {[sparseDescr, Idx2], s, "row 2"}]), + ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo}, + {[sparseDescr, Idx2], "row 2"}]), + ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2], + [sparseStatus,Idx1], [sparseStatus,Idx2]]), + gb(0,5,[[sparseIndex]])), + ?line expect(3, [{[sparseDescr,Idx1], "row 1"}, + {[sparseDescr,Idx2], "row 2"}, + {[sparseStatus,Idx1], ?active}, + {[sparseStatus,Idx2], ?active}, + {[sparseStr,0], "slut"}]), + % Delete the rows + s([{[sparseStatus, Idx1], i, ?destroy}]), + ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]), + s([{[sparseStatus, Idx2], i, ?destroy}]), + ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]). + + +%% Req. Test1 +cnt_64_test(MA) -> + ?LOG("start cnt64 test (~p)",[MA]), + snmpa:verbosity(MA,trace), + ?LOG("start cnt64 test",[]), + p("Testing Counter64, and at the same time, RowStatus is not last column"), + + ?DBG("get cnt64",[]), + g([[cnt64,0]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(1, noSuchName, 1, any), + expect(1, [{[cnt64,0],18446744073709551615}])), + ?DBG("get-next cnt64",[]), + gn([[cnt64]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]), + expect(2, [{[cnt64,0],18446744073709551615}])), + ?DBG("send cntTrap",[]), + snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"}, + {cnt64, 10}, + {sysLocation, "here"}]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"}, + {[sysLocation,0], "here"}]), + expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [1]}, + {[sysContact,0], "pelle"}, + {[cnt64,0], 10}, + {[sysLocation,0], "here"}])), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + ?DBG("create row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]), + ?DBG("create row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]), + + ?DBG("get-next (cntIndex)",[]), + gn([[cntIndex]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]), + expect(3, [{[cntCnt,Idx1], 0}])), + % Delete the rows + ?DBG("delete row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(4, [{[cntStatus, Idx1], ?destroy}]), + ?DBG("delete row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(5, [{[cntStatus, Idx2], ?destroy}]), + catch snmpa:verbosity(MA,log), + ?DBG("done",[]), + ok. + +%% Req. Test1 +opaque_test() -> + p("Testing Opaque datatype..."), + g([[opaqueObj,0]]), + ?line expect(1, [{[opaqueObj,0], "opaque-data"}]). + +%% Req. OLD-SNMPEA-MIB +api_test(MaNode) -> + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [intAgentIpAddress]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, + oid_to_name, [OID]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [[1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, + int_to_enum, ['RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]), + ?line case snmp:date_and_time() of + List when list(List), length(List) == 8 -> ok; + List when list(List), length(List) == 11 -> ok + end. + +%% Req. Klas3 +api_test2() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]), + g([[fname4,0]]), + ?line expect(2, [{[fname4,0], 1}]). + +api_test3() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]). + + +unreg_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[snmpInPkts, 0], any}]). + +load_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[fname,0], ""}]). + +%% Req. Klas1 +load_test_sa() -> + gn([[?v1_2(sysServices,sysORLastChange), 0]]), + ?line expect(1, [{[fname,0], any}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_get() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0], Key1c4, [fname,0],Key1c3, + [sysName,0]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,0], "test"}]), + g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]), + ?line ?v1_2(expect(2, noSuchName, [1,4], any), + expect(2, [{[1,3,7,1], noSuchObject}, + {Key1c4, 2}, + {[sysDescr,0], "Erlang SNMP agent"}, + {[1,3,7,2], noSuchObject}, + {Key1c3, 2}, + {[sysDescr,0], "Erlang SNMP agent"}])). + +%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3. +do_mul_get_err() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]), + ?line ?v1_2(expect(1, noSuchName, 5, any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,2], noSuchInstance}])), + g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname3,0], noSuchObject}, + {Key1c3, 2}, + {[sysName,1], noSuchInstance}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, {[fname,0], "test set"}, + {Key1c3, 2}, {[sysName,0], "test"}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next_err() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[1,3,6,999], endOfMibView}, + {[fname,0], "test set"}, + {[1,3,90], endOfMibView}, + {Key1c3, 2}, + {[sysName,0], "test"}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set() -> + p("Adding one row in subagent table, and one in master table"), + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [sysLocation,0], + [friendsEntry, [3, 3]]]), + ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"}, + {[sysLocation,0], "new_value"}, + {[friendsEntry, [3, 3]], ?active}]), + g([NewKeyc4]), + ?line expect(3, [{NewKeyc4, 2}]), + s([{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]), + ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + p("Adding one row in subagent table, and one in master table"), + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {NewKeyc3, 2}, + {[sysUpTime,0], 45}, % sysUpTime (readOnly) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any), + g([[friendsEntry, [2, 3]]]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])), + g([NewKeyc4]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB +sa_mib() -> + g([[sa, [2,0]]]), + ?line expect(1, [{[sa, [2,0]], 3}]), + s([{[sa, [1,0]], s, "sa_test"}]), + ?line expect(2, [{[sa, [1,0]], "sa_test"}]). + +ma_trap1(MA) -> + snmpa:send_trap(MA, testTrap2, "standard trap"), + ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]), + snmpa:send_trap(MA, testTrap1, "standard trap"), + ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]). + +ma_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap2(MA) -> + snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1}, + {ifAdminStatus, [1], 1}, + {ifOperStatus, [1], 2}]), + ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}]). + +sa_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]], + "pelle"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}]). + +ma_v2_trap1(MA) -> + ?DBG("ma_v2_traps -> entry with MA = ~p => " + "send standard trap: testTrapv22",[MA]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]), + snmpa:send_trap(MA, testTrapv21, "standard trap"), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmp ++ [1]}]). + +ma_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}]). + +%% Note: This test case takes a while... actually a couple of minutes. +ma_v2_inform1(MA) -> + ?DBG("ma_v2_inform -> entry with MA = ~p => " + "send notification: testTrapv22",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag1, self()}, + "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag1, [_]} -> + ok; + {snmp_targets, tag1, Addrs1} -> + ?line ?FAIL({bad_addrs, Addrs1}) + after + 5000 -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag1, {got_response, _}} -> + ok; + {snmp_notification, tag1, {no_response, _}} -> + ?line ?FAIL(no_response) + after + 20000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + + %% + %% -- The rest is possibly erroneous... + %% + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag2, self()}, + "standard inform", []), + ?line expect(2, {inform, false}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag2, [_]} -> + ok; + {snmp_targets, tag2, Addrs2} -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]), + ?line ?FAIL({bad_addrs, Addrs2}) + after + 5000 -> + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag2, {got_response, _}} -> + ?line ?FAIL(got_response); + {snmp_notification, tag2, {no_response, _}} -> + ok + after + 240000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag2) timeout",[]), + ?line ?FAIL(nothing_at_all) + end. + + +ma_v1_2_v2_trap(MA) -> + snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmpTraps ++ [3]}, + {[ifIndex, 1], 1}, + {[snmpTrapEnterprise, 0], [1,2,3]}]). + + +ma_v1_2_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}, + {[snmpTrapEnterprise, 0], ?system}]). + + +sa_v1_2_v2_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + +sa_v1_2_v2_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], "pelle"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +sa_v1_2_v2_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 2]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_bad_value() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2}, + {[sa, [2,0]], 5}, % badValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, badValue, 2, any), + s([{NewKeyc3, 2}, + {[sa, [2,0]], 6}, % wrongValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, ?v1_2(badValue, wrongValue), 2, any), + g([NewKeyc4]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_gen_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2},{NewKeyc4, 2}, + {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]), + ?line expect(1, genErr, 4, any), +% The row might have been added; we don't know. +% (as a matter of fact we do - it is added, because the agent +% first sets its own vars, and then th SAs. Lets destroy it. + s([{NewKeyc5, ?destroy}]), + ?line expect(2, [{NewKeyc5, ?destroy}]). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_too_big() -> + g([[sa, [4,0]]]), + ?line expect(1, tooBig). + +%% Req. Klas1, system group, snmp group (v1/v2) +next_across_sa() -> + gn([[sysDescr],[klas1,5]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {[snmpInPkts, 0], any}]). + +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2} +%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2} +%% Req. Klas3, Klas4 +undo_test() -> + s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]), + ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any), + s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]), + ?line expect(3, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]), + ?line expect(4, ?v1_2(genErr, commitFailed), 1, any), +% unfortunatly we don't know if we'll get undoFailed or commitFailed. +% it depends on which order the agent traverses the varbind list. +% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]), +% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]), + ?line expect(6, genErr, 2, any). + +%% Req. Klas3, Klas4 +bad_return() -> + g([[fStatus4,4], + [fName4,4]]), + ?line expect(4, genErr, 2, any), + g([[fStatus4,5], + [fName4,5]]), + ?line expect(5, genErr, 1, any), + g([[fStatus4,6], + [fName4,6]]), + ?line expect(6, genErr, 2, any), + gn([[fStatus4,7], + [fName4,7]]), + ?line expect(7, genErr, 2, any), + gn([[fStatus4,8], + [fName4,8]]), + ?line expect(8, genErr, 1, any), + gn([[fStatus4,9], + [fName4,9]]), + ?line expect(9, genErr, 2, any). + + +%%%----------------------------------------------------------------- +%%% Test the implementation of standard mibs. +%%% We should *at least* try to GET all variables, just to make +%%% sure the instrumentation functions work. +%%% Note that many of the functions in the standard mib is +%%% already tested by the normal tests. +%%%----------------------------------------------------------------- +standard_mibs(suite) -> + [snmp_standard_mib, snmp_community_mib, + snmp_framework_mib, + snmp_target_mib, snmp_notification_mib, + snmp_view_based_acm_mib]. + +standard_mibs_2(suite) -> + [snmpv2_mib_2, snmp_community_mib_2, + snmp_framework_mib_2, + snmp_target_mib_2, snmp_notification_mib_2, + snmp_view_based_acm_mib_2]. + +standard_mibs_3(suite) -> + [snmpv2_mib_3,snmp_framework_mib_3, snmp_mpd_mib_3, + snmp_target_mib_3, snmp_notification_mib_3, + snmp_view_based_acm_mib_3, snmp_user_based_sm_mib_3]. + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v1. +%% o Test the counters and control objects in SNMP-STANDARD-MIB +%%----------------------------------------------------------------- +snmp_standard_mib(suite) -> []; +snmp_standard_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?DBG("snmp_standard_mib -> std_mib_init", []), + try_test(std_mib_init), + + ?DBG("snmp_standard_mib -> std_mib_a", []), + InBadVsns = try_test(std_mib_a), + put(vsn, v2), + ?DBG("snmp_standard_mib -> std_mib_read", []), + try_test(std_mib_read), + put(vsn, v1), + + ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]), + Bad = try_test(std_mib_b, [InBadVsns]), + ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []), + try_test(std_mib_read, [], [{community, "bad community"}]), + ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []), + try_test(std_mib_write, [], [{community, "public"}]), + ?DBG("snmp_standard_mib -> std_mib_asn_err", []), + try_test(std_mib_asn_err), + ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]), + try_test(std_mib_c, [Bad]), + ?DBG("snmp_standard_mib -> std_mib_a", []), + try_test(standard_mib_a), + + ?DBG("snmp_standard_mib -> std_mib_finish", []), + try_test(std_mib_finish), + ?DBG("snmp_standard_mib -> std_mib_test_finish", []), + try_test(standard_mib_test_finish, [], [{community, "bad community"}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_a() -> + ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]), + ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]), + ?line OutPkts2 = OutPkts + 1, + %% There are some more counters we could test here, but it's not that + %% important, since they are removed from SNMPv2-MIB. + ok. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_init() -> + %% disable authentication failure traps. (otherwise w'd get many of + %% them - this is also a test to see that it works). + s([{[snmpEnableAuthenTraps,0], 2}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_finish() -> + %% enable again + s([{[snmpEnableAuthenTraps,0], 1}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_test_finish() -> + %% force a authenticationFailure + std_mib_write(), + %% check that we got a trap + ?line expect(2, trap, [1,2,3], 4, 0, []). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_read() -> + ?DBG("std_mib_read -> entry", []), + g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply + ?DBG("std_mib_read -> await timeout (i.e. no reply)", []), + ?line expect(1, timeout). % make sure we don't get a trap! + + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_write() -> + ?DBG("std_mib_write -> entry", []), + s([{[sysLocation, 0], "new_value"}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_asn_err() -> + snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]). + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v2 and v3. +%% o Test the counters and control objects in SNMPv2-MIB +%%----------------------------------------------------------------- +snmpv2_mib_2(suite) -> []; +snmpv2_mib_2(Config) when list(Config) -> + ?LOG("snmpv2_mib_2 -> start",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?DBG("snmpv2_mib_2 -> standard mib init",[]), + try_test(std_mib_init), + + ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]), + InBadVsns = try_test(std_mib_a), + + ?DBG("snmpv2_mib_2 -> make a bad version read",[]), + put(vsn, v1), + try_test(std_mib_read), + + ?DBG("snmpv2_mib_2 -> bad version read",[]), + put(vsn, v2), + Bad = try_test(std_mib_b, [InBadVsns]), + + ?DBG("snmpv2_mib_2 -> read with bad community",[]), + try_test(std_mib_read, [], [{community, "bad community"}]), + + ?DBG("snmpv2_mib_2 -> write with public community",[]), + try_test(std_mib_write, [], [{community, "public"}]), + + ?DBG("snmpv2_mib_2 -> asn err",[]), + try_test(std_mib_asn_err), + + ?DBG("snmpv2_mib_2 -> check counters",[]), + try_test(std_mib_c, [Bad]), + + ?DBG("snmpv2_mib_2 -> get som counters",[]), + try_test(snmpv2_mib_a), + + ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]), + try_test(std_mib_finish), + + ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, " + "then disable auth traps",[]), + try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]), + + ?LOG("snmpv2_mib_2 -> done",[]). + +%% Req. SNMPv2-MIB +snmpv2_mib_3(suite) -> []; +snmpv2_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + InBadVsns = try_test(std_mib_a), + put(vsn, v1), + try_test(std_mib_read), + put(vsn, v3), + _Bad = try_test(std_mib_b, [InBadVsns]), + try_test(snmpv2_mib_a), + + try_test(std_mib_finish). + +-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]). + +%% Req. SNMPv2-MIB +snmpv2_mib_test_finish() -> + %% force a authenticationFailure + ?DBG("ma_v2_inform -> write to std mib",[]), + std_mib_write(), + + %% check that we got a trap + ?DBG("ma_v2_inform -> await trap",[]), + ?line expect(2, v2trap, [{[sysUpTime,0], any}, + {[snmpTrapOID,0], ?authenticationFailure}]), + + %% and the the inform + ?DBG("ma_v2_inform -> await inform",[]), + ?line expect(2, {inform,true}, [{[sysUpTime,0], any}, + {[snmpTrapOID,0],?authenticationFailure}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_a() -> + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + + ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]), + InBadVsns. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_b(InBadVsns) -> + ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]), + ?line InBadVsns2 = InBadVsns + 1, + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] = + get_req(4, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + {InBadCommunityNames, InBadCommunityUses, InASNErrs}. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) -> + ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] = + get_req(1, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + ?line InBadCommunityNames2 = InBadCommunityNames + 1, + ?line InBadCommunityUses2 = InBadCommunityUses + 1, + ?line InASNErrs2 = InASNErrs + 1. + +%% Req. SNMPv2-MIB +snmpv2_mib_a() -> + ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]), + s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]), + ?line expect(3, [{[snmpSetSerialNo,0], SetSerial}, + {[sysLocation, 0], "val2"}]), + s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]), + ?line expect(4, inconsistentValue, 2, + [{[sysLocation, 0], "val3"}, + {[snmpSetSerialNo,0], SetSerial}]), + ?line ["val2"] = get_req(5, [[sysLocation,0]]). + + +%%----------------------------------------------------------------- +%% o Bad community uses/name is tested already +%% in SNMPv2-MIB and STANDARD-MIB. +%% o Test add/deletion of rows. +%%----------------------------------------------------------------- +snmp_community_mib(suite) -> []; +snmp_community_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + try_test(snmp_community_mib), + ?line unload_master("SNMP-COMMUNITY-MIB"). + +snmp_community_mib_2(X) -> snmp_community_mib(X). + +%% Req. SNMP-COMMUNITY-MIB +snmp_community_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o Test engine boots / time +%%----------------------------------------------------------------- +snmp_framework_mib(suite) -> []; +snmp_framework_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + try_test(snmp_framework_mib), + ?line unload_master("SNMP-FRAMEWORK-MIB"). + +snmp_framework_mib_2(X) -> snmp_framework_mib(X). + +snmp_framework_mib_3(suite) -> []; +snmp_framework_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(snmp_framework_mib). + + +%% Req. SNMP-FRAMEWORK-MIB +snmp_framework_mib() -> + ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]), + ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]), + sleep(5000), + ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]), + if + EngineTime+7 < EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + EngineTime+4 > EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + true -> ok + end, + ?line case get_req(4, [[snmpEngineBoots,0]]) of + [Boots] when integer(Boots) -> ok; + Else -> ?FAIL(Else) + end, + ok. + +%%----------------------------------------------------------------- +%% o Test the counters +%%----------------------------------------------------------------- +snmp_mpd_mib_3(suite) -> []; +snmp_mpd_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + UnknownPDUHs = try_test(snmp_mpd_mib_a), + try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]), + try_test(snmp_mpd_mib_c, [UnknownPDUHs]). + + +%% Req. SNMP-MPD-MIB +snmp_mpd_mib_a() -> + ?line [UnknownSecs, InvalidMsgs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0]]), + Pdu = #pdu{type = 'get-request', + request_id = 23, + error_status = noError, + error_index = 0, + varbinds = []}, + SPdu = #scopedPdu{contextEngineID = "agentEngine", + contextName = "", + data = Pdu}, + ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu), + V3Hdr1 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [7], + msgSecurityModel = 23, % bad sec model + msgSecurityParameters = []}, + V3Hdr2 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [6], % bad flag combination + msgSecurityModel = 3, + msgSecurityParameters = []}, + Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1, + data = SPDUBytes}, + Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2, + data = SPDUBytes}, + ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1), + ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2), + snmp_test_mgr:send_bytes(MsgBytes1), + snmp_test_mgr:send_bytes(MsgBytes2), + + ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0], + [snmpUnknownPDUHandlers, 0]]), + ?line UnknownSecs2 = UnknownSecs + 1, + ?line InvalidMsgs2 = InvalidMsgs + 1, + UnknownPDUHs. + +-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]). +snmp_mpd_mib_b() -> + g([[sysUpTime,0]]), + ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]). + + +snmp_mpd_mib_c(UnknownPDUHs) -> + ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]), + ?line UnknownPDUHs2 = UnknownPDUHs + 1. + + +snmp_target_mib(suite) -> []; +snmp_target_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-TARGET-MIB"), + try_test(snmp_target_mib), + ?line unload_master("SNMP-TARGET-MIB"). + +snmp_target_mib_2(X) -> snmp_target_mib(X). + +snmp_target_mib_3(X) -> snmp_target_mib(X). + +snmp_target_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +snmp_notification_mib(suite) -> []; +snmp_notification_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + try_test(snmp_notification_mib), + ?line unload_master("SNMP-NOTIFICATION-MIB"). + +snmp_notification_mib_2(X) -> snmp_notification_mib(X). + +snmp_notification_mib_3(X) -> snmp_notification_mib(X). + +snmp_notification_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o add/delete views and try them +%% o try boundaries +%%----------------------------------------------------------------- +snmp_view_based_acm_mib(suite) -> []; +snmp_view_based_acm_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master("Test2"), + snmp_view_based_acm_mib(), + ?line unload_master("Test2"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib() -> + snmpa:verbosity(net_if,trace), + snmpa:verbosity(master_agent,trace), + ?LOG("start snmp_view_based_acm_mib test",[]), + %% The user "no-rights" is present in USM, and is mapped to security + %% name 'no-rights", which is not present in VACM. + %% So, we'll add rights for it, try them and delete them. + %% We'll give "no-rights" write access to tDescr.0 and read access + %% to tDescr2.0 + %% These are the options we'll use to the mgr + Opts = [{user, "no-rights"}, {community, "no-rights"}], + %% Find the valid secmodel, and one invalid secmodel. + {SecMod, InvSecMod} = + case get(vsn) of + v1 -> {?SEC_V1, ?SEC_V2C}; + v2 -> {?SEC_V2C, ?SEC_USM}; + v3 -> {?SEC_USM, ?SEC_V1} + end, + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Now, add a mapping from "no-rights" -> "no-rights-group" + GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]], + GRow1 = + [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"}, + {GRow1Status, ?createAndGo}], + ?DBG("set '~p'",[GRow1]), + ?line try_test(do_set, [GRow1]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Create a mapping for another sec model, and make sure it dosn't + %% give us access + GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]], + GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"}, + {GRow2Status, ?createAndGo}], + + ?DBG("set '~p'",[GRow2]), + ?line try_test(do_set, [GRow2]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [GRow2Status]), + + RVName = "rv_name", + WVName = "wv_name", + + %% Access row + ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1], + ARow1Status = [vacmAccessStatus, ARow1Idx], + ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1}, + {[vacmAccessReadViewName, ARow1Idx], RVName}, + {[vacmAccessWriteViewName, ARow1Idx], WVName}, + {ARow1Status, ?createAndGo}], + + %% This access row would give acces, if InvSecMod was valid. + ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1], + ARow2Status = [vacmAccessStatus, ARow2Idx], + ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1}, + {[vacmAccessReadViewName, ARow2Idx], "internet"}, + {[vacmAccessWriteViewName, ARow2Idx], "internet"}, + {ARow2Status, ?createAndGo}], + + ?line try_test(do_set, [ARow2]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [ARow2Status]), + + + %% Add valid row + ?line try_test(do_set, [ARow1]), + + ?line try_test(use_no_rights, [], Opts), + + %% Create the view family + VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access + VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access + VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access + VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access + VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx], + VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx], + VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx], + VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx], + + ?line try_test(add_row, [VRow1Status]), + ?line try_test(add_row, [VRow2Status]), + ?line try_test(add_row, [VRow3Status]), + + %% We're supposed to have access now... + ?line try_test(use_rights, [], Opts), + + %% Change Row3 to Row4 + ?line try_test(del_row, [VRow3Status]), + ?line try_test(add_row, [VRow4Status]), + + %% We should still have access... + ?line try_test(use_rights, [], Opts), + + %% Delete rows + ?line try_test(del_row, [GRow1Status]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete rest of rows + ?line try_test(del_row, [ARow1Status]), + ?line try_test(del_row, [VRow1Status]), + ?line try_test(del_row, [VRow2Status]), + ?line try_test(del_row, [VRow4Status]), + + ?line try_test(use_no_rights, [], Opts), + snmpa:verbosity(master_agent,log). + +do_set(Row) -> + s(Row), + expect(1, Row). + +add_row(RowStatus) -> + s([{RowStatus, ?createAndGo}]), + expect(1, [{RowStatus, ?createAndGo}]). + +del_row(RowStatus) -> + s([{RowStatus, ?destroy}]), + expect(1, [{RowStatus, ?destroy}]). + + + +use_no_rights() -> + g([[xDescr,0]]), + ?v1_2_3(expect(11, noSuchName, 1, any), + expect(12, [{[xDescr,0], noSuchObject}]), + expect(13, authorizationError, 1, any)), + g([[xDescr2,0]]), + ?v1_2_3(expect(21, noSuchName, 1, any), + expect(22, [{[xDescr2,0], noSuchObject}]), + expect(23, authorizationError, 1, any)), + gn([[xDescr]]), + ?v1_2_3(expect(31, noSuchName, 1, any), + expect(32, [{[xDescr], endOfMibView}]), + expect(33, authorizationError, 1, any)), + s([{[xDescr,0], "tryit"}]), + ?v1_2_3(expect(41, noSuchName, 1, any), + expect(42, noAccess, 1, any), + expect(43, authorizationError, 1, any)). + + +use_rights() -> + g([[xDescr,0]]), + expect(1, [{[xDescr,0], any}]), + g([[xDescr2,0]]), + expect(2, [{[xDescr2,0], any}]), + s([{[xDescr,0], "tryit"}]), + expect(3, noError, 0, any), + g([[xDescr,0]]), + expect(4, [{[xDescr,0], "tryit"}]). + +mk_ln(X) -> + [length(X) | X]. + +%%----------------------------------------------------------------- +%% o add/delete users and try them +%% o test all secLevels +%% o test all combinations of protocols +%% o try bad ops; check counters +%%----------------------------------------------------------------- +snmp_user_based_sm_mib_3(suite) -> []; +snmp_user_based_sm_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + _AgentDir = ?config(agent_dir, Config), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + + %% The newUser used here already has VACM access. + + %% Add a new user in the simplest way; just createAndGo + try_test(v3_sync, [[{usm_add_user1, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new user + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"), + DesKey1 = lists:sublist(ShaKey1, 16), + + %% Change the new user's keys - 1 + try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + MgrDir = ?config(mgr_dir, Config), + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"), + DesKey2 = lists:sublist(ShaKey2, 16), + + %% Change the new user's keys - 2 + ?line try_test(v3_sync, + [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + reset_usm_mgr(MgrDir), + ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2), + ?line load_master("Test2"), + ?line try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Change the new user's keys - 3 + ?line try_test(v3_sync, + [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new keys + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Try some read requests + ?line try_test(v3_sync, [[{usm_read, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Delete the new user + ?line try_test(v3_sync, [[{usm_del_user, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try some bad requests + ?line try_test(v3_sync, [[{usm_bad, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("SNMP-USER-BASED-SM-MIB"). + +-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]). + +usm_add_user1() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +usm_use_user() -> + v2_proc(). + + +%% Change own public keys +usm_key_change1(ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_shaxxxxxxxxxx", + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_desxxxxxx", + DesKey), + Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change own private keys +usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change other's public keys +usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}], + s(Vbs1), + ?line expect(1, noAccess, 1, any), + Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs2), + ?line expect(2, noAccess, 1, any), + + + Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs3), + ?line expect(1, Vbs3). + +usm_read() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ?line g([[usmUserSecurityName, NewRowIndex], + [usmUserCloneFrom, NewRowIndex], + [usmUserAuthKeyChange, NewRowIndex], + [usmUserOwnAuthKeyChange, NewRowIndex], + [usmUserPrivKeyChange, NewRowIndex], + [usmUserOwnPrivKeyChange, NewRowIndex]]), + ?line expect(1, + [{[usmUserSecurityName, NewRowIndex], "newUser"}, + {[usmUserCloneFrom, NewRowIndex], [0,0]}, + {[usmUserAuthKeyChange, NewRowIndex], ""}, + {[usmUserOwnAuthKeyChange, NewRowIndex], ""}, + {[usmUserPrivKeyChange, NewRowIndex], ""}, + {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]), + ok. + + + +usm_del_user() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]). + +-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]). + +-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]). + +-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]). + +-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]). + +-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]). + +usm_bad() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, inconsistentName, 1, any), + + RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs2), + ?line expect(2, wrongValue, 1, any), + + RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs3), + ?line expect(3, Vbs3), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]), + ?line expect(4, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]), + ?line expect(5, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]), + ?line expect(6, wrongValue, 1, any), + ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]), + ?line expect(7, wrongValue, 1, any), + + Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs4), + ?line expect(1, Vbs4), + + ok. + + +%%----------------------------------------------------------------- +%% Loop through entire MIB, to make sure that all instrum. funcs +%% works. +%% Load all std mibs that are not loaded by default. +%%----------------------------------------------------------------- +loop_mib(suite) -> []; +loop_mib(Config) when list(Config) -> + ?LOG("loop_mib -> initiate case",[]), + %% snmpa:verbosity(master_agent,debug), + %% snmpa:verbosity(mib_server,info), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]), + ?line load_master_std("SNMP-MPD-MIB"), + ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?DBG("loop_mib -> try",[]), + try_test(loop_mib_1), + ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]), + ?line unload_master("SNMP-MPD-MIB"), + ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + %% snmpa:verbosity(master_agent,log), + %% snmpa:verbosity(mib_server,silence), + ?LOG("loop_mib -> done",[]). + + +loop_mib_2(suite) -> []; +loop_mib_2(Config) when list(Config) -> + ?LOG("loop_mib_2 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_2 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_2 -> load mibs",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_2 -> unload mibs",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?LOG("loop_mib_2 -> done",[]). + + +loop_mib_3(suite) -> []; +loop_mib_3(Config) when list(Config) -> + ?LOG("loop_mib_3 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_3 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_3 -> load mibs",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_3 -> unload mibs",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?LOG("loop_mib_3 -> done",[]). + + +%% Req. As many mibs all possible +loop_mib_1() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_1([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_1(Oid, N) -> + ?DBG("loop_it_1 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_1 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_1 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_1(NOid, N+1); + #pdu{type='get-response', error_status=noSuchName, error_index=1, + varbinds=[_]} -> + ?DBG("loop_it_1 -> done",[]), + N; + + #pdu{type = Type, error_status = Err, error_index = Idx, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs}) + end. + +%% Req. As many mibs all possible +loop_mib_2() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_2([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_2(Oid, N) -> + ?DBG("loop_it_2 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid, value = endOfMibView}]} -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p",[NOid]), + N; + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_2 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_2(NOid, N+1) + end. + + +%%%----------------------------------------------------------------- +%%% Testing of reported bugs and other tickets. +%%%----------------------------------------------------------------- + +reported_bugs(suite) -> + [otp_1128, otp_1129, otp_1131, otp_1162, + otp_1222, otp_1298, otp_1331, otp_1338, + otp_1342, otp_2776, otp_2979, otp_3187, otp_3725]. + +reported_bugs_2(suite) -> + [otp_1128_2, otp_1129_2, otp_1131_2, otp_1162_2, + otp_1222_2, otp_1298_2, otp_1331_2, otp_1338_2, + otp_1342_2, otp_2776_2, otp_2979_2, otp_3187_2]. + +reported_bugs_3(suite) -> + [otp_1128_3, otp_1129_3, otp_1131_3, otp_1162_3, + otp_1222_3, otp_1298_3, otp_1331_3, otp_1338_3, + otp_1342_3, otp_2776_3, otp_2979_3, otp_3187_3, + otp_3542]. + + +%% These are (ticket) test cases where the initiation has to be done +%% individually. +tickets(suite) -> + [otp_4394]. + +%%----------------------------------------------------------------- +%% Ticket: OTP-1128 +%% Slogan: Bug in handling of createAndWait set-requests. +%%----------------------------------------------------------------- +otp_1128(suite) -> []; +otp_1128(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1128), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1128_2(X) -> otp_1128(X). + +otp_1128_3(X) -> otp_1128(X). + +otp_1128() -> + io:format("Testing bug reported in ticket OTP-1128...~n"), + + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + + s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(29, [{NewKeyc5, ?notReady}]), + s([{NewKeyc5, ?active}, {NewKeyc3, 2}]), + ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(31, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(32, [{NewKeyc5, ?destroy}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1129, OTP-1169 +%% Slogan: snmpa:int_to_enum crashes on bad oids +%%----------------------------------------------------------------- +otp_1129(suite) -> []; +otp_1129(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + try_test(otp_1129_i, [node()]), + ?line unload_master("Klas3"). + +otp_1129_2(X) -> otp_1129(X). + +otp_1129_3(X) -> otp_1129(X). + +otp_1129_i(MaNode) -> + io:format("Testing bug reported in ticket OTP-1129...~n"), + false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]), + false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1131 +%% Slogan: Agent crashes / erlang node halts if RowIndex in a +%% setrequest is of bad type, e.g. an INDEX {INTEGER}, +%% and RowIdenx [3,2]. +%%----------------------------------------------------------------- +otp_1131(suite) -> []; +otp_1131(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas1"), + try_test(otp_1131), + ?line unload_master("Klas1"). + +otp_1131_2(X) -> otp_1131(X). + +otp_1131_3(X) -> otp_1131(X). + +otp_1131() -> + io:format("Testing bug reported in ticket OTP-1131...~n"), + s([{[friendsEntry, [2, 3, 1]], s, "kompis3"}, + {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1162 +%% Slogan: snmp_agent can't handle wrongValue from instrum.func +%%----------------------------------------------------------------- +otp_1162(suite) -> []; +otp_1162(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + try_test(otp_1162), + stop_subagent(SA). + +otp_1162_2(X) -> otp_1162(X). + +otp_1162_3(X) -> otp_1162(X). + +otp_1162() -> + s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok) + ?line expect(1, ?v1_2(badValue, wrongValue), 1, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1222 +%% Slogan: snmp agent crash if faulty index is returned from instrum +%%----------------------------------------------------------------- +otp_1222(suite) -> []; +otp_1222(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + ?line load_master("Klas4"), + try_test(otp_1222), + ?line unload_master("Klas3"), + ?line unload_master("Klas4"). + +otp_1222_2(X) -> otp_1222(X). + +otp_1222_3(X) -> otp_1222(X). + +otp_1222() -> + io:format("Testing bug reported in ticket OTP-1222...~n"), + s([{[fStatus4,1], 4}, {[fName4,1], 1}]), + ?line expect(1, genErr, 0, any), + s([{[fStatus4,2], 4}, {[fName4,2], 1}]), + ?line expect(2, genErr, 0, any). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1298 +%% Slogan: Negative INTEGER values are treated as positive. +%%----------------------------------------------------------------- +otp_1298(suite) -> []; +otp_1298(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1298), + ?line unload_master("Klas2"). + +otp_1298_2(X) -> otp_1298(X). + +otp_1298_3(X) -> otp_1298(X). + +otp_1298() -> + io:format("Testing bug reported in ticket OTP-1298...~n"), + s([{[fint,0], -1}]), + ?line expect(1298, [{[fint,0], -1}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1331 +%% Slogan: snmp_generic should return noError when deleting non-ex row +%%----------------------------------------------------------------- +otp_1331(suite) -> []; +otp_1331(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1331), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1331_2(X) -> otp_1331(X). + +otp_1331_3(X) -> otp_1331(X). + +otp_1331() -> + NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")], + s([{NewKeyc5, ?destroy}]), + ?line expect(1, [{NewKeyc5, ?destroy}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1338 +%% Slogan: snmp bug in initialisation of default values for mnesia tabs +%%----------------------------------------------------------------- +otp_1338(suite) -> []; +otp_1338(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1338), + ?line unload_master("Klas2"). + +otp_1338_2(X) -> otp_1338(X). + +otp_1338_3(X) -> otp_1338(X). + +otp_1338() -> + s([{[kStatus2, 7], i, ?createAndGo}]), + ?line expect(1, [{[kStatus2, 7], ?createAndGo}]), + g([[kName2, 7]]), + ?line expect(2, [{[kName2, 7], "JJJ"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1342 +%% Slogan: default impl of snmp table can't handle bad index access, +%% Set when INDEX is read-write gets into an infinite loop! +%%----------------------------------------------------------------- +otp_1342(suite) -> []; +otp_1342(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas4"), + try_test(otp_1342), + ?line unload_master("Klas4"). + +otp_1342_2(X) -> otp_1342(X). + +otp_1342_3(X) -> otp_1342(X). + +otp_1342() -> + s([{[fIndex5, 1], i, 1}, + {[fName5, 1], i, 3}, + {[fStatus5, 1], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1366 +%% Slogan: snmp traps not sent to all managers +%% Note: NYI! We need a way to tell the test server that we need +%% mgrs on two different machines. +%%----------------------------------------------------------------- +otp_1366(suite) -> []; +otp_1366(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1366), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1366_2(X) -> otp_1366(X). + +otp_1366_3(X) -> otp_1366(X). + +otp_1366() -> + ?INF("NOT YET IMPLEMENTED", []), + 'NYI'. + +%%----------------------------------------------------------------- +%% Ticket: OTP-2776 +%% Slogan: snmp:validate_date_and_time() fails when time is 00:00 +%%----------------------------------------------------------------- +otp_2776(suite) -> []; +otp_2776(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_2776). + +otp_2776_2(X) -> otp_2776(X). + +otp_2776_3(X) -> otp_2776(X). + +otp_2776() -> + io:format("Testing bug reported in ticket OTP-2776...~n"), + + Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0], + Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00 + Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0], + Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0], + Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0], + Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0], + Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2 + Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0], + Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4 + Dt10_invalid = [], + Dt11_invalid = [kalle,hobbe], + L = [{ 1, true, Dt01_valid}, + { 2, true, Dt02_valid}, + { 3, true, Dt03_valid}, + { 4, false, Dt04_invalid}, + { 5, true, Dt05_valid}, + { 6, true, Dt06_valid}, + { 7, false, Dt07_invalid}, + { 8, true, Dt08_valid}, + { 9, false, Dt09_invalid}, + {10, false, Dt10_invalid}, + {11, false, Dt11_invalid}], + + ?line ok = validate_dat(L). + + +validate_dat(L) -> validate_dat(L,[]). + +validate_dat([],V) -> + Fun = fun({_,X}) -> case X of + ok -> false; + _ -> true + end + end, + validate_dat1( lists:reverse( lists:filter(Fun,V) ) ); +validate_dat([{Id,E,Dat}|T],V) -> + validate_dat(T,[validate_dat2(Id,E,Dat) | V]). + +validate_dat1([]) -> ok; +validate_dat1(L) -> {error,L}. + +validate_dat2(Id, E, Dat) -> + Res = case {E,snmp:validate_date_and_time(Dat)} of + {E,E} -> ok; + {E,A} -> {E,A} + end, + {Id, Res}. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-2979 +%% Slogan: get-next on more than 1 column in an empty table +%% returns bad response. +%%----------------------------------------------------------------- +otp_2979(suite) -> []; +otp_2979(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Test1"), + ?line init_old(), + try_test(otp_2979), + ?line unload_master("Test1"). + +otp_2979_2(X) -> otp_2979(X). + +otp_2979_3(X) -> otp_2979(X). + +otp_2979() -> + gn([[sparseDescr], [sparseStatus]]), + ?line expect(1, [{[sparseStr,0], "slut"}, + {[sparseStr,0], "slut"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3187 +%% Slogan: get-next on vacmAccessTable for colums > 5 returns +%% endOfTable - should return value. +%%----------------------------------------------------------------- +otp_3187(suite) -> []; +otp_3187(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + otp_3187(), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +otp_3187_2(X) -> otp_3187(X). + +otp_3187_3(X) -> otp_3187(X). + +otp_3187() -> + ?line Elements = + snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]), + lists:foreach(fun(E) -> + ?line if E == endOfTable -> + ?FAIL(endOfTable); + true -> ok + end + end, Elements). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3542 +%% Slogan: +%%----------------------------------------------------------------- +otp_3542(suite) -> []; +otp_3542(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_3542). + +otp_3542() -> + io:format("SNMP v3 discovery...~n"), + ?line Res = snmp_test_mgr:d(), + io:format("SNMP v3 discovery result: ~p~n",[Res]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-3725 +%% Slogan: Slow response time on snmpa:int_to_enum +%%----------------------------------------------------------------- +otp_3725(suite) -> []; +otp_3725(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_3725_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +%% Req. OLD-SNMPEA-MIB +otp_3725_test(MaNode) -> + io:format("Testing feature requested in ticket OTP-3725...~n"), + ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]), + ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]), + ?DBG("otp_3725_test -> Db = ~p",[Db]), + + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [Db, intAgentIpAddress]), + ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name, + [Db,OID]), + ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [Db, [1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [Db, intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum, + [Db, 'RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]), + ok. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-4394 +%% Slogan: Target mib tag list check invalid +%%----------------------------------------------------------------- + + +otp_4394(suite) -> {req, [], {conf, + init_otp_4394, + [otp_4394_test], + finish_otp_4394}}. + +init_otp_4394(Config) when list(Config) -> + ?DBG("init_otp_4394 -> entry with" + "~n Config: ~p", [Config]), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line otp_4394_config(AgentDir, MgrDir, Ip), + MasterAgentVerbosity = {master_agent_verbosity, trace}, + NetIfVerbosity = {net_if_verbosity, trace}, + Opts = [MasterAgentVerbosity,NetIfVerbosity], + [{vsn, v1} | start_v1_agent(Config,Opts)]. + +otp_4394_config(AgentDir, MgrDir, Ip0) -> + ?DBG("otp_4394_config -> entry with" + "~n AgentDir: ~p" + "~n MgrDir: ~p" + "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]), + Vsn = [v1], + Ip = tuple_to_list(Ip0), + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip, + ?TRAP_UDP, Ip, 4000, + "OTP-4394 test"), + ?line case update_usm(Vsn, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsn, MgrDir); + false -> + ?line ok + end, + C1 = {"a", "all-rights", "initial", "", "pc"}, + C2 = {"c", "secret", "secret_name", "", "secret_tag"}, + ?line write_community_conf(AgentDir, [C1, C2]), + ?line update_vacm(Vsn, AgentDir), + Ta1 = {"shelob v1", + [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda + "pc1", + "target_v1", "", + %% [255,255,255,255,0,0], + [], + 2048}, + Ta2 = {"bifur v1", + [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip + "pc2", + "target_v1", "", + %% [255,255,255,255,0,0], + [], 2048}, + ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]), + ?line write_target_params_conf(AgentDir, Vsn), + ?line write_notify_conf(AgentDir), + ok. + + + +finish_otp_4394(Config) when list(Config) -> + ?DBG("finish_otp_4394 -> entry", []), + C1 = stop_agent(Config), + delete_files(C1), + erase(mgr_node), + lists:keydelete(vsn, 1, C1). + +otp_4394_test(suite) -> []; +otp_4394_test(Config) -> + ?DBG("otp_4394_test -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_4394_test1), + ?DBG("otp_4394_test -> done", []), + ok. + +otp_4394_test1() -> + ?DBG("otp_4394_test1 -> entry", []), + gn([[1,1]]), + Res = + case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of + %% {error, 1, {"?",[]}, {"~w",[timeout]}} + {error, 1, _, {_, [timeout]}} -> + ?DBG("otp_4394_test1 -> expected result: timeout", []), + ok; + Else -> + Else + end, + ?DBG("otp_4394_test1 -> done with: ~p", [Res]), + Res. + + +%%%-------------------------------------------------- +%%% Used to test the standard mib with our +%%% configuration. +%%%-------------------------------------------------- +run(F, A, Opts) -> + M = get(mib_dir), + Dir = get(mgr_dir), + User = snmp_misc:get_option(user, Opts, "all-rights"), + SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv), + EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"), + CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID), + Community = snmp_misc:get_option(community, Opts, "all-rights"), + ?DBG("run -> start crypto app",[]), + Crypto = case os:type() of + vxworks -> + no_crypto; + _ -> + ?CRYPTO_START() + end, + ?DBG("run -> Crypto: ~p",[Crypto]), + catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + ?DBG("run -> config:~n" + "\tM: ~p~n" + "\tDir: ~p~n" + "\tUser: ~p~n" + "\tSecLevel: ~p~n" + "\tEngineID: ~p~n" + "\tCtxEngineID: ~p~n" + "\tCommunity: ~p~n" + "\tStdM: ~p", + [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]), + case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()}, + {packet_server_debug,true}, + {debug,true}, + {agent, get(master_host)}, + {agent_udp, 4000}, + {trap_udp, 5000}, + {recbuf,65535}, + quiet, + get(vsn), + {community, Community}, + {user, User}, + {sec_level, SecLevel}, + {engine_id, EngineID}, + {context_engine_id, CtxEngineID}, + {dir, Dir}, + {mibs, mibs(StdM, M)}]) of + {ok, _Pid} -> + Res = apply(?MODULE, F, A), + catch snmp_test_mgr:stop(), + Res; + Err -> + io:format("Error starting manager: ~p\n", [Err]), + catch snmp_test_mgr:stop(), + ?line exit({mgr_start, Err}) + end. + + +mibs(StdMibDir,MibDir) -> + [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")), + join(MibDir, "OLD-SNMPEA-MIB.bin"), + join(StdMibDir, "SNMP-FRAMEWORK-MIB"), + join(StdMibDir, "SNMP-MPD-MIB"), + join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"), + join(StdMibDir, "SNMP-USER-BASED-SM-MIB"), + join(StdMibDir, "SNMP-TARGET-MIB"), + join(StdMibDir, "SNMP-NOTIFICATION-MIB"), + join(MibDir, "Klas1.bin"), + join(MibDir, "Klas2.bin"), + join(MibDir, "Klas3.bin"), + join(MibDir, "Klas4.bin"), + join(MibDir, "SA-MIB.bin"), + join(MibDir, "TestTrap.bin"), + join(MibDir, "Test1.bin"), + join(MibDir, "Test2.bin"), + join(MibDir, "TestTrapv2.bin")]. + +join(D,F) -> + filename:join(D,F). + +%% string used in index +is(S) -> [length(S) | S]. + +try_test(Func) -> + call(get(mgr_node), ?MODULE, run, [Func, [], []]). + +try_test(Func, A) -> + call(get(mgr_node), ?MODULE, run, [Func, A, []]). + +try_test(Func, A, Opts) -> + call(get(mgr_node), ?MODULE, run, [Func, A, Opts]). + +call(N,M,F,A) -> + ?DBG("call -> entry with~n" + " N: ~p~n" + " M: ~p~n" + " F: ~p~n" + " A: ~p~n" + " when~n" + " get(): ~p", + [N,M,F,A,get()]), + spawn(N, ?MODULE, wait, [self(),get(),M,F,A]), + receive + {done, {'EXIT', Rn}, Loc} -> + ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]), + put(test_server_loc, Loc), + exit(Rn); + {done, Ret, Zed} -> + ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]), + Ret + end. + +wait(From, Env, M, F, A) -> + ?DBG("wait -> entry with ~n" + "\tFrom: ~p~n" + "\tEnv: ~p",[From,Env]), + lists:foreach(fun({K,V}) -> put(K,V) end, Env), + Rn = (catch apply(M, F, A)), + ?DBG("wait -> Rn: ~n~p", [Rn]), + From ! {done, Rn, get(test_server_loc)}, + exit(Rn). + +expect(A,B) -> ok = snmp_test_mgr:expect(A,B). +expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C). +expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D). +expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F). + +get_req(Id, Vars) -> + ?DBG("get_req -> entry with~n" + "\tId: ~p~n" + "\tVars: ~p",[Id,Vars]), + g(Vars), + ?DBG("get_req -> await response",[]), + {ok, Val} = snmp_test_mgr:get_response(Id, Vars), + ?DBG("get_req -> response: ~p",[Val]), + Val. + +get_next_req(Vars) -> + ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]), + gn(Vars), + ?DBG("get_next_req -> await response",[]), + Response = snmp_test_mgr:receive_response(), + ?DBG("get_next_req -> response: ~p",[Response]), + Response. + + + +start_node(Name) -> + ?LOG("start_node -> entry with Name: ~p",[Name]), + M = list_to_atom(?HOSTNAME(node())), + ?DBG("start_node -> M: ~p",[M]), + Pa = filename:dirname(code:which(?MODULE)), + ?DBG("start_node -> Pa: ~p",[Pa]), + + Args = case init:get_argument('CC_TEST') of + {ok, [[]]} -> + " -pa /clearcase/otp/libraries/snmp/ebin "; + {ok, [[Path]]} -> + " -pa " ++ Path; + error -> + "" + end, + %% Do not use start_link!!! (the proc that calls this one is tmp) + ?DBG("start_node -> Args: ~p~n",[Args]), + A = Args ++ " -pa " ++ Pa, + case (catch ?START_NODE(Name, A)) of + {ok, Node} -> + %% Tell the test_server to not clean up things it never started. + ?DBG("start_node -> Node: ~p",[Node]), + {ok, Node}; + Else -> + ?ERR("start_node -> failed with(other): Else: ~p",[Else]), + ?line ?FAIL(Else) + end. + + +stop_node(Node) -> + ?LOG("stop_node -> Node: ~p",[Node]), + rpc:cast(Node, erlang, halt, []). + +p(X) -> + io:format(user, X++"\n", []). + +sleep(X) -> + receive + after + X -> ok + end. + +%%%----------------------------------------------------------------- +%%% Configuration +%%%----------------------------------------------------------------- +config(Vsns, MgrDir, AgentDir, MIp, AIp) -> + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp, + ?TRAP_UDP, AIp, 4000, + "test"), + ?line case update_usm(Vsns, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsns, MgrDir); + false -> + ?line ok + end, + ?line update_community(Vsns, AgentDir), + ?line update_vacm(Vsns, AgentDir), + ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns), + ?line write_target_params_conf(AgentDir, Vsns), + ?line write_notify_conf(AgentDir), + ok. + +delete_files(Config) -> + Dir = ?config(agent_dir, Config), + {ok, List} = file:list_dir(Dir), + lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end, + List). + +update_usm(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +update_usm_mgr(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +rewrite_usm_mgr(Dir, ShaKey, DesKey) -> + ?line ok = file:rename(filename:join(Dir,"usm.conf"), + filename:join(Dir,"usm.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + file:close(Fid). + +reset_usm_mgr(Dir) -> + ?line ok = file:rename(filename:join(Dir,"usm.old"), + filename:join(Dir,"usm.conf")). + + +update_community([v3], _Dir) -> ok; +update_community(_, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n", + []), + file:close(Fid). + + +-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]). +update_vacm(_Vsn, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]), + ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", " + "~w, excluded, null}.\n", [?tDescr_instance]), + file:close(Fid). + + +vacm_ver(v1) -> v1; +vacm_ver(v2) -> v2c; +vacm_ver(v3) -> usm. + + +write_community_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write), + ok = write_community_conf1(Fid, Confs), + file:close(Fid). + +write_community_conf1(_, []) -> + ok; +write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) -> + ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n", + [ComIdx, ComName, SecName, CtxName, TransTag]), + write_community_conf1(Fid, Confs). + + +write_target_addr_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + ok = write_target_addr_conf1(Fid, Confs), + file:close(Fid). + + +write_target_addr_conf1(_, []) -> + ok; +write_target_addr_conf1(Fid, + [{Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz}|Confs]) -> + ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", + [Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz]), + write_target_addr_conf1(Fid, Confs). + +write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + lists:foreach(fun(Vsn) -> + ok = io:format(Fid, + "{\"~s\", ~w, ~w, 1500, 3, " + "\"std_trap\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, mk_param(Vsn)]), + case Vsn of + v1 -> ok; + v2 -> + ok = io:format(Fid, + "{\"~s.2\",~w,~w,1500,3, " + "\"std_inform\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]); + v3 -> + ok = io:format(Fid, + "{\"~s.3\",~w,~w,1500,3, " + "\"std_inform\", \"~s\", " + "\"mgrEngine\", [], 1024}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]) + end + end, + Vsns), + file:close(Fid). + +mk_param(v1) -> "target_v1"; +mk_param(v2) -> "target_v2"; +mk_param(v3) -> "target_v3". + +mk_ip([A,B,C,D], Vsn) -> + io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]). + + +rewrite_target_addr_conf(Dir,NewPort) -> + TAFile = filename:join(Dir, "target_addr.conf"), + ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]), + case file:read_file_info(TAFile) of + {ok, _} -> ok; + {error, R} -> ?ERR("failure reading file info of " + "target address config file: ~p",[R]), + ok + end, + + ?line [TrapAddr|Addrs] = + snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end), + + ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]), + + NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs], + + ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]), + + ?line ok = file:rename(filename:join(Dir,"target_addr.conf"), + filename:join(Dir,"target_addr.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + + ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs), + + file:close(Fid). + +rewrite_target_addr_conf1(O) -> + {ok,O}. + +rewrite_target_addr_conf2(NewPort,{Name,Ip,_Port,Timeout,Retry, + "std_trap",EngineId}) -> + ?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]), + {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; +rewrite_target_addr_conf2(_NewPort,O) -> + ?LOG("rewrite_target_addr_conf2 -> entry with " + "~n O: ~p",[O]), + O. + + +rewrite_target_addr_conf3(_,[]) -> ok; +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry, + ParamName,EngineId}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % ParamsName + "\"~s\"}.", % EngineId + [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]), + rewrite_target_addr_conf3(Fid,T); +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList, + ParamName,EngineId,TMask,MMS}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % TagList + "\"~s\", " % ParamsName + "\"~s\"," % EngineId + "~p, " % TMask + "~p}.", % MMS + [Name,Ip,Port,Timeout,Retry,TagList,ParamName, + EngineId,TMask,MMS]), + rewrite_target_addr_conf3(Fid,T). + +reset_target_addr_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_addr.old"), + filename:join(Dir,"target_addr.conf")). + +write_target_params_conf(Dir, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + lists:foreach(fun(Vsn) -> + MP = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> v3 + end, + SM = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> usm + end, + ok = io:format(Fid, "{\"target_~w\", ~w, ~w, " + "\"all-rights\", noAuthNoPriv}.~n", + [Vsn, MP, SM]) + end, + Vsns), + file:close(Fid). + +rewrite_target_params_conf(Dir, SecName, SecLevel) -> + ?line ok = file:rename(filename:join(Dir,"target_params.conf"), + filename:join(Dir,"target_params.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n", + [SecName, SecLevel]), + file:close(Fid). + +reset_target_params_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_params.old"), + filename:join(Dir,"target_params.conf")). + +write_notify_conf(Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write), + ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []), + ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []), + file:close(Fid). + +ver_to_trap_str([v1]) -> "v1"; +ver_to_trap_str([v2]) -> "v2"; +% default is to use the latest snmp version +ver_to_trap_str([v1,v2]) -> "v2". + + + +write_view_conf(Dir) -> + {ok, Fid} = file:open(a(Dir,"view.conf"),write), + ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []), + ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]), + file:close(Fid). + +a(A,B) -> lists:append(A,B). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +copy_file(From, To) -> + {ok, Bin} = file:read_file(From), + ok = file:write_file(To, Bin). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +display_memory_usage() -> + Info = snmpa:info(snmp_master_agent), + TreeSize = lists_key1search(tree_size_bytes, Info), + ProcMem = lists_key1search(process_memory, Info), + MibDbSize = lists_key1search([db_memory,mib], Info), + NodeDbSize = lists_key1search([db_memory,node], Info), + TreeDbSize = lists_key1search([db_memory,tree], Info), + ?INF("Memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p", + [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]). + +lists_key1search([], Res) -> + Res; +lists_key1search([Key|Keys], List) when atom(Key), list(List) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + lists_key1search(Keys, Val); + false -> + undefined + end; +lists_key1search(Key, List) when atom(Key) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + Val; + false -> + undefined + end. + + +regs() -> + lists:sort(registered()). diff --git a/lib/snmp/test/snmp_agent_nfilter_test.erl b/lib/snmp/test/snmp_agent_nfilter_test.erl new file mode 100644 index 0000000000..269c7c96c9 --- /dev/null +++ b/lib/snmp/test/snmp_agent_nfilter_test.erl @@ -0,0 +1,78 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: +%%---------------------------------------------------------------------- +-module(snmp_agent_nfilter_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + all/1, + init_per_testcase/2, fin_per_testcase/2 + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + ]). + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +%%====================================================================== +%% Test case definitions +%%====================================================================== +all(_) -> + ?SKIP(not_yet_implemented). + + +%%====================================================================== +%% Test functions +%%====================================================================== + + +%%====================================================================== +%% Internal functions +%%====================================================================== diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl new file mode 100644 index 0000000000..53b35058e1 --- /dev/null +++ b/lib/snmp/test/snmp_agent_test.erl @@ -0,0 +1,6009 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_agent_test). + +%% TODO +%% * Test fault-tolerance (kill master etc) +%% + +-compile(export_all). + +-define(application, snmp). + +-include_lib("kernel/include/file.hrl"). +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). +%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl"). + + +-define(klas1, [1,3,6,1,2,1,7]). +-define(klas2, [1,3,6,1,2,1,9]). +-define(klas3, [1,3,6,1,2,1,8,1]). +-define(klas4, [1,3,6,1,2,1,8,4]). +-define(sa, [1,3,6,1,4,1,193,2]). +-define(system, [1,3,6,1,2,1,1]). +-define(snmp, [1,3,6,1,2,1,11]). +-define(snmpTraps, [1,3,6,1,6,3,1,1,5]). +-define(ericsson, [1,3,6,1,4,1,193]). +-define(testTrap, [1,3,6,1,2,1,15,0]). +-define(xDescr, [1,3,6,1,2,1,17,1]). +-define(xDescr2, [1,3,6,1,2,1,17,2]). + +-define(active, 1). +-define(notInService, 2). +-define(notReady, 3). +-define(createAndGo, 4). +-define(createAndWait, 5). +-define(destroy, 6). + +-define(TRAP_UDP, 5000). + +-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"). + +-define(str(X), snmp_pdus:bits_to_str(X)). + +-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n", + [?LINE, self()]), + receive cont -> ok end + end). + + +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + +-define(v1_2_3(V1,V2,V3), + case get(vsn) of + v1 -> V1; + v2 -> V2; + _ -> V3 + end). + + +all(suite) -> + {req, + [ + mnesia, + distribution, + {local_slave_nodes, 2}, + {time, 360} + ], + [{conf, init_all, cases(), finish_all}]}. + + +init_per_testcase(otp_7157_test = _Case, Config) when is_list(Config) -> + ?DBG("init_per_testcase -> entry with" + "~n Case: ~p" + "~n Config: ~p", [_Case, Config]), + Dog = ?WD_START(?MINS(1)), + [{watchdog, Dog}|Config]; +init_per_testcase(v2_inform_i = _Case, Config) when is_list(Config) -> + ?DBG("init_per_testcase -> entry with" + "~n Case: ~p" + "~n Config: ~p", [_Case, Config]), + Dog = ?WD_START(?MINS(10)), + [{watchdog, Dog}|Config]; +init_per_testcase(v3_inform_i = _Case, Config) when is_list(Config) -> + ?DBG("init_per_testcase -> entry with" + "~n Case: ~p" + "~n Config: ~p", [_Case, Config]), + Dog = ?WD_START(?MINS(10)), + [{watchdog, Dog}|Config]; +init_per_testcase(_Case, Config) when is_list(Config) -> + ?DBG("init_per_testcase -> entry with" + "~n Case: ~p" + "~n Config: ~p", [_Case, Config]), + Dog = ?WD_START(?MINS(6)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + ?DBG("fin_per_testcase -> entry with" + "~n Case: ~p" + "~n Config: ~p", [_Case, Config]), + Dog = ?config(watchdog, Config), + ?WD_STOP(Dog), + Config. + +cases() -> + case ?OSTYPE() of + vxworks -> + %% No crypto app, so skip v3 testcases + [ + misc, + test_v1, + test_v2, + test_v1_v2, + test_multi_threaded, + mib_storage, + tickets + ]; + _Else -> + [ + misc, + test_v1, + test_v2, + test_v1_v2, + test_v3, + test_multi_threaded, + mib_storage, + tickets + ] + end. + + +%%%----------------------------------------------------------------- +%%% The test case structure is as follows: +%%% +%%% init_all - starts mnesia, +%%% +%%% init_v1 - starts agent +%%% simple +%%% big - e.g. starts/stops subagent, load/unloads mibs +%%% init_mul +%%% mul_get +%%% mul_set +%%% <etc> +%%% finish_mul +%%% <etc> +%%% finish_v1 +%%% +%%% init_v2 - starts agent +%%% finish_v2 +%%% +%%% init_bilingual - starts agent +%%% finish_bilingual +%%% +%%% finish_all +%%% +%%% There is still one problem with these testsuites. If one test +%%% fails, it may not be possible to run some other cases, as it +%%% may have e.g. created some row or loaded some table, that it +%%% didn't undo (since it failed). +%%%----------------------------------------------------------------- + +init_all(Conf) -> + ?DISPLAY_SUITE_INFO(), + snmp_agent_test_lib:init_all(Conf). + +finish_all(Conf) -> + snmp_agent_test_lib:finish_all(Conf). + +start_v1_agent(Config) -> + snmp_agent_test_lib:start_v1_agent(Config). + +start_v1_agent(Config, Opts) -> + snmp_agent_test_lib:start_v1_agent(Config, Opts). + +start_v2_agent(Config) -> + snmp_agent_test_lib:start_v2_agent(Config). + +start_v2_agent(Config, Opts) -> + snmp_agent_test_lib:start_v2_agent(Config, Opts). + +start_v3_agent(Config) -> + snmp_agent_test_lib:start_v3_agent(Config). + +start_v3_agent(Config, Opts) -> + snmp_agent_test_lib:start_v3_agent(Config, Opts). + +start_bilingual_agent(Config) -> + snmp_agent_test_lib:start_bilingual_agent(Config). + +start_multi_threaded_agent(Config) when is_list(Config) -> + snmp_agent_test_lib:start_mt_agent(Config). + +stop_agent(Config) -> + snmp_agent_test_lib:stop_agent(Config). + + +create_tables(SaNode) -> + ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables}, + {attributes, [a1,a2]}]). + +delete_tables() -> + mnesia:delete_table(friendsTable2), + mnesia:delete_table(kompissTable2), + mnesia:delete_table(snmp_variables). + +%% Creation is done in runtime! +delete_mib_storage_mnesia_tables() -> + mnesia:delete_table(snmpa_mib_data), + mnesia:delete_table(snmpa_mib_tree), + mnesia:delete_table(snmpa_symbolic_store). + + +%%----------------------------------------------------------------- +%% A test case is always one of: +%% - v1 specific case +%% - v2 specific case +%% - v1 and v2 case +%% All v1 specific cases are prefixed with v1_, and all v2 with +%% v2_. E.g. v1_trap/v2_trap. +%% +%% All other cases are shared. However, the testserver uses the name +%% of the case to generate a file for that case. The same case cannot +%% be used in different configurations in the same suite. Therefore +%% all these functions exists in two variants, the base function +%% <base>, and a second version <base>_2. There may be several +%% versions as well, <base>_N. +%%----------------------------------------------------------------- +mib_storage(suite) -> [ + mib_storage_ets, + mib_storage_dets, + mib_storage_mnesia, + mib_storage_size_check_ets, + mib_storage_size_check_dets, + mib_storage_size_check_mnesia, + mib_storage_varm_dets, + mib_storage_varm_mnesia + ]. + +mib_storage_ets(suite) -> {req, [], {conf, init_mib_storage_ets, + mib_storage_ets_cases(), + finish_mib_storage_ets}}. + +mib_storage_dets(suite) -> {req, [], {conf, init_mib_storage_dets, + mib_storage_dets_cases(), + finish_mib_storage_dets}}. + +mib_storage_mnesia(suite) -> {req, [], {conf, init_mib_storage_mnesia, + mib_storage_mnesia_cases(), + finish_mib_storage_mnesia}}. + +mib_storage_size_check_ets(suite) -> + {req, [], {conf, + init_size_check_mse, + mse_size_check_cases(), + finish_size_check_mse}}. + +mib_storage_size_check_dets(suite) -> + {req, [], {conf, + init_size_check_msd, + msd_size_check_cases(), + finish_size_check_msd}}. + +mib_storage_size_check_mnesia(suite) -> + {req, [], {conf, + init_size_check_msm, + msm_size_check_cases(), + finish_size_check_msm}}. + +mib_storage_varm_dets(suite) -> + {req, [], {conf, + init_varm_mib_storage_dets, + varm_mib_storage_dets_cases(), + finish_varm_mib_storage_dets}}. + +mib_storage_varm_mnesia(suite) -> + {req, [], {conf, + init_varm_mib_storage_mnesia, + varm_mib_storage_mnesia_cases(), + finish_varm_mib_storage_mnesia}}. + +mib_storage_ets_cases() -> + [ + mse_simple, + mse_v1_processing, + mse_big, + mse_big2, + mse_loop_mib, + mse_api, + mse_sa_register, + mse_v1_trap, + mse_sa_error, + mse_next_across_sa, + mse_undo, + mse_standard_mib, + mse_community_mib, + mse_framework_mib, + mse_target_mib, + mse_notification_mib, + mse_view_based_acm_mib, + mse_sparse_table, + mse_me_of, + mse_mib_of]. + +mib_storage_dets_cases() -> + [ + msd_simple, + msd_v1_processing, + msd_big, + msd_big2, + msd_loop_mib, + msd_api, + msd_sa_register, + msd_v1_trap, + msd_sa_error, + msd_next_across_sa, + msd_undo, + msd_standard_mib, + msd_community_mib, + msd_framework_mib, + msd_target_mib, + msd_notification_mib, + msd_view_based_acm_mib, + msd_sparse_table, + msd_me_of, + msd_mib_of + ]. + +mib_storage_mnesia_cases() -> + [ + msm_simple, + msm_v1_processing, + msm_big, + msm_big2, + msm_loop_mib, + msm_api, + msm_sa_register, + msm_v1_trap, + msm_sa_error, + msm_next_across_sa, + msm_undo, + msm_standard_mib, + msm_community_mib, + msm_framework_mib, + msm_target_mib, + msm_notification_mib, + msm_view_based_acm_mib, + msm_sparse_table, + msm_me_of, + msm_mib_of + ]. + +mse_size_check_cases() -> + [mse_size_check]. + +msd_size_check_cases() -> + [msd_size_check]. + +msm_size_check_cases() -> + [msm_size_check]. + +varm_mib_storage_dets_cases() -> + [msd_varm_mib_start]. + +varm_mib_storage_mnesia_cases() -> + [msm_varm_mib_start]. + +init_mib_storage_ets(Config) when is_list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,ets}, + init_ms(Config, [MibStorage]). + +init_mib_storage_dets(Config) when is_list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + init_ms(Config, [MibStorage]). + +init_mib_storage_mnesia(Config) when is_list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + init_ms(Config, [MibStorage]). + +init_ms(Config, Opts) when is_list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts], + [{vsn, v1} | start_v1_agent(Config,Opts1)]. + +init_size_check_mse(Config) when is_list(Config) -> + MibStorage = {snmp_mib_storage, ets}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msd(Config) when is_list(Config) -> + AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage, {dets, AgentDir}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msm(Config) when is_list(Config) -> + MibStorage = {snmp_mib_storage, {mnesia,[]}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_ms(Config, Opts) when is_list(Config) -> + SaNode = ?GCONF(snmp_sa, Config), + %% We are using v3 here, so crypto must be supported or else... + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + create_tables(SaNode), + AgentDir = ?GCONF(agent_dir, Config), + MgrDir = ?GCONF(mgr_dir, Config), + Ip = ?GCONF(ip, Config), + ?line ok = + config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_v3_agent(Config, Opts)]. + +init_varm_mib_storage_dets(Config) when is_list(Config) -> + ?LOG("init_varm_mib_storage_dets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +init_varm_mib_storage_mnesia(Config) when is_list(Config) -> + ?LOG("init_varm_mib_storage_mnesia -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +finish_mib_storage_ets(Config) when is_list(Config) -> + ?LOG("finish_mib_storage_ets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_dets(Config) when is_list(Config) -> + ?LOG("finish_mib_storage_dets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_mnesia(Config) when is_list(Config) -> + ?LOG("finish_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_dets(Config) when is_list(Config) -> + ?LOG("finish_varm_mib_storage_dets -> entry", []), + delete_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_mnesia(Config) when is_list(Config) -> + ?LOG("finish_varm_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_size_check_mse(Config) when is_list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msd(Config) when is_list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msm(Config) when is_list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_ms(Config) when is_list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + + +%% These are just interface functions to fool the test server +mse_simple(X) -> ?P(mse_simple), simple(X). +mse_v1_processing(X) -> ?P(mse_v1_processing), v1_processing(X). +mse_big(X) -> ?P(mse_big), big(X). +mse_big2(X) -> ?P(mse_big2), big2(X). +mse_loop_mib(X) -> ?P(mse_loop_mib), loop_mib(X). +mse_api(X) -> ?P(mse_api), api(X). +mse_sa_register(X) -> ?P(mse_sa_register), sa_register(X). +mse_v1_trap(X) -> ?P(mse_v1_trap), v1_trap(X). +mse_sa_error(X) -> ?P(mse_sa_error), sa_error(X). +mse_next_across_sa(X) -> ?P(mse_next_across_sa), next_across_sa(X). +mse_undo(X) -> ?P(mse_undo), undo(X). +mse_standard_mib(X) -> ?P(mse_standard_mib), snmp_standard_mib(X). +mse_community_mib(X) -> ?P(mse_community_mib), snmp_community_mib(X). +mse_framework_mib(X) -> ?P(mse_framework_mib), snmp_framework_mib(X). +mse_target_mib(X) -> ?P(mse_target_mib), snmp_target_mib(X). +mse_notification_mib(X) -> ?P(mse_notification_mib), snmp_notification_mib(X). +mse_view_based_acm_mib(X) -> ?P(mse_view_based_acm_mib), snmp_view_based_acm_mib(X). +mse_sparse_table(X) -> ?P(mse_sparse_table), sparse_table(X). +mse_me_of(X) -> ?P(mse_me_of), ms_me_of(X). +mse_mib_of(X) -> ?P(mse_mib_of), ms_mib_of(X). + +msd_simple(X) -> ?P(msd_simple), simple(X). +msd_v1_processing(X) -> ?P(msd_v1_processing), v1_processing(X). +msd_big(X) -> ?P(msd_big), big(X). +msd_big2(X) -> ?P(msd_big2), big2(X). +msd_loop_mib(X) -> ?P(msd_loop_mib), loop_mib(X). +msd_api(X) -> ?P(msd_api), api(X). +msd_sa_register(X) -> ?P(msd_sa_register), sa_register(X). +msd_v1_trap(X) -> ?P(msd_v1_trap), v1_trap(X). +msd_sa_error(X) -> ?P(msd_sa_error), sa_error(X). +msd_next_across_sa(X) -> ?P(msd_next_across_sa), next_across_sa(X). +msd_undo(X) -> ?P(msd_undo), undo(X). +msd_standard_mib(X) -> ?P(msd_standard_mib), snmp_standard_mib(X). +msd_community_mib(X) -> ?P(msd_community_mib), snmp_community_mib(X). +msd_framework_mib(X) -> ?P(msd_framework_mib), snmp_framework_mib(X). +msd_target_mib(X) -> ?P(msd_target_mib), snmp_target_mib(X). +msd_notification_mib(X) -> ?P(msd_notification_mib), snmp_notification_mib(X). +msd_view_based_acm_mib(X) -> ?P(msd_view_based_acm_mib), snmp_view_based_acm_mib(X). +msd_sparse_table(X) -> ?P(msd_sparse_table), sparse_table(X). +msd_me_of(X) -> ?P(msd_me_of), ms_me_of(X). +msd_mib_of(X) -> ?P(msd_mib_of), ms_mib_of(X). + +msm_simple(X) -> ?P(msm_simple), simple(X). +msm_v1_processing(X) -> ?P(msm_v1_processing), v1_processing(X). +msm_big(X) -> ?P(msm_big2), big(X). +msm_big2(X) -> ?P(msm_loop_mib), big2(X). +msm_loop_mib(X) -> ?P(msm_loop_mib), loop_mib(X). +msm_api(X) -> ?P(msm_api), api(X). +msm_sa_register(X) -> ?P(msm_sa_register), sa_register(X). +msm_v1_trap(X) -> ?P(msm_v1_trap), v1_trap(X). +msm_sa_error(X) -> ?P(msm_sa_error), sa_error(X). +msm_next_across_sa(X) -> ?P(msm_next_across_sa), next_across_sa(X). +msm_undo(X) -> ?P(msm_undo), undo(X). +msm_standard_mib(X) -> ?P(msm_standard_mib), snmp_standard_mib(X). +msm_community_mib(X) -> ?P(msm_community_mib), snmp_community_mib(X). +msm_framework_mib(X) -> ?P(msm_framework_mib), snmp_framework_mib(X). +msm_target_mib(X) -> ?P(msm_target_mib), snmp_target_mib(X). +msm_notification_mib(X) -> ?P(msm_notification_mib), snmp_notification_mib(X). +msm_view_based_acm_mib(X) -> ?P(msm_view_based_acm_mib), snmp_view_based_acm_mib(X). +msm_sparse_table(X) -> ?P(msm_sparse_table), sparse_table(X). +msm_me_of(X) -> ?P(msm_me_of), ms_me_of(X). +msm_mib_of(X) -> ?P(msm_mib_of), ms_mib_of(X). + + +mse_size_check(X) -> ?P(mse_size_check), ms_size_check(X). +msd_size_check(X) -> ?P(msd_size_check), ms_size_check(X). +msm_size_check(X) -> ?P(msm_size_check), ms_size_check(X). + +msd_varm_mib_start(X) -> + ?P(msd_varm_mib_start), + varm_mib_start(X). + +msm_varm_mib_start(X) -> + %% <CONDITIONAL-SKIP> + Skippable = [win32], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(X, Condition), + %% </CONDITIONAL-SKIP> + + ?P(msm_varm_mib_start), + varm_mib_start(X). + +ms_size_check(suite) -> []; +ms_size_check(Config) when is_list(Config) -> + ?P(ms_size_check), + init_case(Config), + ?LOG("mib server size check...", []), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMPv2-MIB"), + ?line load_master_std("SNMPv2-TM"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMPv2-MIB"), + ?line unload_master("SNMPv2-TM"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + + +varm_mib_start(suite) -> []; +varm_mib_start(Config) when is_list(Config) -> + ?P(varm_mib_start), + ?LOG("varm_mib_start -> entry", []), + init_case(Config), + + %% Start the agent + Opts = ?GCONF(agent_opts, Config), + Config1 = start_v1_agent(Config, Opts), + + %% Sleep some in order for the agent to start properly + ?DBG("varm_mib_start -> sleep some (before loading mobs)", []), + ?SLEEP(5000), + + %% Load all the mibs + HardwiredMibs = loaded_mibs(), + ?DBG("varm_mib_start -> load all mibs", []), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + + %% Unload the hardwired mibs + ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []), + ?SLEEP(1000), + ?DBG("varm_mib_start -> unload (hardwired) mibs", []), + ?line unload_mibs(HardwiredMibs), %% unload hardwired + + ?DBG("varm_mib_start -> sleep some (before stopping agent)", []), + ?SLEEP(1000), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + Config2 = stop_agent(Config1), + + %% Sleep some in order for the agent to stop properly + ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []), + ?SLEEP(5000), + + %% Start the agent (again) + ?DBG("varm_mib_start -> start the agent", []), + Config3 = start_v1_agent(Config2, Opts), + + ?DBG("varm_mib_start -> sleep some (before starting tests)", []), + ?SLEEP(5000), + + %% Perform the test(s) + ?DBG("varm_mib_start -> perform the tests", []), + try_test(snmp_community_mib), + try_test(snmp_framework_mib), + try_test(snmp_target_mib), + try_test(snmp_notification_mib), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + stop_agent(Config3), + ok. + + +-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]). +-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]). +-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +ms_me_of(suite) -> []; +ms_me_of(Config) when is_list(Config) -> + ?P(ms_me_of), + init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = me_of(?snmpTrapCommunity_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = me_of(?vacmViewSpinLock_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +me_of(Oid) -> + case snmpa:me_of(Oid) of + {ok, #me{oid = Oid}} -> + ok; + {ok, #me{oid = OtherOid}} -> + case lists:reverse(Oid) of + [0|Rest] -> + case lists:reverse(Rest) of + OtherOid -> + ok; + AnotherOid -> + {error, {invalid_oid, Oid, AnotherOid}} + end; + _ -> + {error, {invalid_oid, Oid, OtherOid}} + end; + {error, Reason} -> + {error, Reason}; + Else -> + {error, Else} + end. + + +ms_mib_of(suite) -> []; +ms_mib_of(Config) when is_list(Config) -> + ?P(ms_mib_of), + init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance, + 'SNMP-USER-BASED-SM-MIB'), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +mib_of(Oid, ExpectedMibName) -> + ?DBG("mib_of -> entry with" + "~n Oid: ~p" + "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]), + %% case snmpa:mib_of(Oid) of + MibOf = snmpa:mib_of(Oid), + ?DBG("mib_of -> MibOf: ~n~p", [MibOf]), + case MibOf of + {ok, ExpectedMibName} -> + ok; + {ok, OtherMibName} -> + {error, {invalid_mib, ExpectedMibName, OtherMibName}}; + {error, Reason} -> + {error, Reason}; + Else -> + ?DBG("mib_of -> Else: ~n~p", [Else]), + {error, Else} + end. + + +misc(suite) -> + {req, [], {conf, init_misc, misc_cases(), finish_misc}}. + +init_misc(Config) -> + init_v1(Config). + +finish_misc(Config) -> + finish_v1(Config). + +misc_cases() -> + [ + app_info, + info_test + ]. + +app_info(suite) -> []; +app_info(Config) when is_list(Config) -> + ?P(app_info), + SnmpDir = app_dir(snmp), + SslDir = app_dir(ssl), + CryptoDir = app_dir(crypto), + Attr = snmp:module_info(attributes), + AppVsn = + case lists:keysearch(app_vsn, 1, Attr) of + {value, {app_vsn, V}} -> + V; + false -> + "undefined" + end, + io:format("Root dir: ~s~n" + "SNMP: Application dir: ~s~n" + " Application ver: ~s~n" + "SSL: Application dir: ~s~n" + "CRYPTO: Application dir: ~s~n", + [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]), + ok. + +app_dir(App) -> + case code:lib_dir(App) of + D when is_list(D) -> + filename:basename(D); + {error, _Reason} -> + "undefined" + end. + + +test_v1(suite) -> {req, [], {conf, init_v1, v1_cases(), finish_v1}}. + +%v1_cases() -> [loop_mib]; +v1_cases() -> + [ + simple, + db_notify_client, + v1_processing, + big, + big2, + loop_mib, + api, + subagent, + mnesia, + multiple_reqs, + sa_register, + v1_trap, + sa_error, + next_across_sa, + undo, + reported_bugs, + standard_mibs, + sparse_table, + cnt_64, + opaque, + + change_target_addr_config + ]. + +init_v1(Config) when is_list(Config) -> + ?line SaNode = ?config(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v1} | start_v1_agent(Config)]. + +finish_v1(Config) when is_list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v2(suite) -> {req, [], {conf, init_v2, v2_cases(), finish_v2}}. + +v2_cases() -> + [ + simple_2, + v2_processing, + big_2, + big2_2, + loop_mib_2, + api_2, + subagent_2, + mnesia_2, + multiple_reqs_2, + sa_register_2, + v2_trap, + v2_inform, + sa_error_2, + next_across_sa_2, + undo_2, + reported_bugs_2, + standard_mibs_2, + v2_types, + implied, + sparse_table_2, + cnt_64_2, + opaque_2, + v2_caps + ]. + +init_v2(Config) when is_list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_v2_agent(Config)]. + +finish_v2(Config) when is_list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v1_v2(suite) -> + {req, [], {conf, init_v1_v2, v1_v2_cases(), finish_v1_v2}}. + +v1_v2_cases() -> + [simple_bi]. + +init_v1_v2(Config) when is_list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, bilingual} | start_bilingual_agent(Config)]. + +finish_v1_v2(Config) when is_list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v3(suite) -> {req, [], {conf, init_v3, v3_cases(), finish_v3}}. + +v3_cases() -> + [ + simple_3, + v3_processing, + big_3, + big2_3, + api_3, + subagent_3, + mnesia_3, + loop_mib_3, + multiple_reqs_3, + sa_register_3, + v3_trap, + v3_inform, + sa_error_3, + next_across_sa_3, + undo_3, + reported_bugs_3, + standard_mibs_3, + v3_security, + v2_types_3, + implied_3, + sparse_table_3, + cnt_64_3, + opaque_3, + v2_caps_3 + ]. + +init_v3(Config) when is_list(Config) -> + %% Make sure crypto works, otherwise start_agent will fail + %% and we will be stuck with a bunch of mnesia tables for + %% the rest of this suite... + ?DBG("start_agent -> start crypto app",[]), + case os:type() of + vxworks -> + no_crypto; + _ -> + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end + end, + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v3], MgrDir, AgentDir, + tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_v3_agent(Config)]. + +finish_v3(Config) when is_list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_multi_threaded(suite) -> + {req, [], {conf, init_mt, mt_cases(), finish_mt}}. + +mt_cases() -> + [multi_threaded, mt_trap]. + +init_mt(Config) when is_list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = + config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_multi_threaded_agent(Config)]. + +finish_mt(Config) when is_list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +%% This one *must* be run first in each case. +init_case(Config) -> + snmp_agent_test_lib:init_case(Config). + + +load_master(Mib) -> + ?DBG("load_master -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]). + +load_master_std(Mib) -> + ?DBG("load_master_std -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]). + +unload_master(Mib) -> + ?DBG("unload_master -> entry with" + "~n Mib: ~p", [Mib]), + ok = snmpa:unload_mibs(snmp_master_agent, [Mib]). + +loaded_mibs() -> + ?DBG("loaded_mibs -> entry",[]), + Info = snmpa:info(snmp_master_agent), + {value, {mib_server, MibInfo}} = lists:keysearch(mib_server, 1, Info), + {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, MibInfo), + [atom_to_list(Mib) || {Mib,_,_} <- Mibs]. + +unload_mibs(Mibs) -> + ?DBG("unload_mibs -> entry with" + "~n Mibs: ~p", [Mibs]), + ok = snmpa:unload_mibs(snmp_master_agent, Mibs). + +start_subagent(SaNode, RegTree, Mib) -> + snmp_agent_test_lib:start_subagent(SaNode, RegTree, Mib). + +stop_subagent(SA) -> + snmp_agent_test_lib:stop_subagent(SA). + + +%%----------------------------------------------------------------- +%% This function takes care of the old OTP-SNMPEA-MIB. +%% Unfortunately, the testcases were written to use the data in the +%% internal tables, and these table are now obsolete and not used +%% by the agent. Therefore, we emulate them by using +%% OLD-SNMPEA-MIB, which uses the default impl. of all tables. +%% +%% These two rows must exist in intCommunityTable +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. +%% (But with the manager's IP address) +%% +%%----------------------------------------------------------------- +init_old() -> + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [6 | "public"], + {get(mip), "public", 2, 2}), + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [13 | "standard trap"], + {get(mip), "standard trap", 2, 1}), + snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]). + + + +simple(suite) -> []; +simple(Config) when is_list(Config) -> + ?P(simple), + init_case(Config), + + try_test(simple_standard_test). + +simple_2(X) -> ?P(simple_2), simple(X). + +simple_bi(suite) -> []; +simple_bi(Config) when is_list(Config) -> + ?P(simple_bi), + init_case(Config), + + put(vsn, v1), % First, try v1 manager + try_test(simple_standard_test), + + put(vsn, v2), % Then, try v2 manager + try_test(simple_standard_test). + +simple_3(X) -> + ?P(simple_3), simple(X). + +big(suite) -> []; +big(Config) when is_list(Config) -> + ?P(big), + %% put(sname, {?MODULE, big}), + %% put(verbosity, trace), + + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?P1("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?DBG("big -> SA: ~p", [SA]), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + snmpa:dump_mibs(), + snmpa:dump_mibs("dumped_mibs.txt"), + io:format("Local DB: ~n~p~n", [snmpa_local_db:print()]), + + try_test(big_test), + + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB"). + +big_2(X) -> ?P(big_2), big(X). + +big_3(X) -> ?P(big_3), big(X). + + +big2(suite) -> []; +big2(Config) when is_list(Config) -> + ?P(big2), + %% This is exactly the same tests as 'big', but with the + %% v2 equivalent of the mibs. + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?P1("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"), + ?line load_master("OLD-SNMPEA-MIB-v2"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB-v2"). + +big2_2(X) -> ?P(big2_2), big2(X). + +big2_3(X) -> ?P(big2_3), big2(X). + + +multi_threaded(suite) -> []; +multi_threaded(Config) when is_list(Config) -> + ?P(multi_threaded), + init_case(Config), + + ?line load_master("Test1"), + try_test(multi_threaded_test), + ?line unload_master("Test1"). + +mt_trap(suite) -> []; +mt_trap(Config) when is_list(Config) -> + ?P(mt_trap), + init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + ?line load_master("TestTrapv2"), + try_test(mt_trap_test, [MA]), + ?line unload_master("TestTrapv2"), + ?line unload_master("Test1"). + +v2_types(suite) -> []; +v2_types(Config) when is_list(Config) -> + ?P(v2_types), + init_case(Config), + + ?line load_master("Test1"), + try_test(types_v2_test), + ?line unload_master("Test1"). + +v2_types_3(X) -> ?P(v2_types_3), v2_types(X). + + +implied(suite) -> []; +implied(Config) when is_list(Config) -> + ?P(implied), + init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(implied_test,[MA]), + ?line unload_master("Test1"). + +implied_3(X) -> ?P(implied_3), implied(X). + + +sparse_table(suite) -> []; +sparse_table(Config) when is_list(Config) -> + ?P(sparse_table), + init_case(Config), + + ?line load_master("Test1"), + try_test(sparse_table_test), + ?line unload_master("Test1"). + +sparse_table_2(X) -> ?P(sparse_table_2), sparse_table(X). + +sparse_table_3(X) -> ?P(sparse_table_3), sparse_table(X). + +cnt_64(suite) -> []; +cnt_64(Config) when is_list(Config) -> + ?P(cnt_64), + init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(cnt_64_test, [MA]), + ?line unload_master("Test1"). + +cnt_64_2(X) -> ?P(cnt_64_2), cnt_64(X). + +cnt_64_3(X) -> ?P(cnt_64_3), cnt_64(X). + +opaque(suite) -> []; +opaque(Config) when is_list(Config) -> + ?P(opaque), + init_case(Config), + + ?line load_master("Test1"), + try_test(opaque_test), + ?line unload_master("Test1"). + +opaque_2(X) -> ?P(opaque_2), opaque(X). + +opaque_3(X) -> ?P(opaque_2), opaque(X). + + +change_target_addr_config(suite) -> []; +change_target_addr_config(Config) when is_list(Config) -> + ?P(change_target_addr_config), + ?LOG("change_target_addr_config -> entry",[]), + init_case(Config), + + put(sname,snmp_suite), + put(verbosity,trace), + + MA = whereis(snmp_master_agent), + + ?LOG("change_target_addr_config -> load TestTrap",[]), + ?line load_master("TestTrap"), + + ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,trace), + + %% First send some traps that will arive att the original manager + ?LOG("change_target_addr_config -> send trap",[]), + try_test(ma_trap1, [MA]), + + ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,silence), + + %% Start new dummy listener + ?LOG("change_target_addr_config -> start dummy manager",[]), + ?line {ok,Pid,NewPort} = dummy_manager_start(MA), + + %% Reconfigure + ?LOG("change_target_addr_config -> reconfigure",[]), + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_addr_conf(AgentDir, NewPort), + ?line snmp_target_mib:reconfigure(AgentDir), + + %% Send the trap again + ?LOG("change_target_addr_config -> send trap again",[]), + catch dummy_manager_send_trap2(Pid), + + ?LOG("change_target_addr_config -> await trap ack",[]), + catch dummy_manager_await_trap2_ack(), + + ?LOG("change_target_addr_config -> stop dummy manager",[]), + ?line ok = dummy_manager_stop(Pid), + + ?LOG("change_target_addr_config -> reset target address config",[]), + ?line reset_target_addr_conf(AgentDir), + + ?LOG("change_target_addr_config -> unload TestTrap",[]), + ?line unload_master("TestTrap"). + + +dummy_manager_start(MA) -> + ?DBG("dummy_manager_start -> entry",[]), + Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]), + ?DBG("dummy_manager_start -> Pid: ~p",[Pid]), + await_dummy_manager_started(Pid). + +await_dummy_manager_started(Pid) -> + receive + {dummy_manager_started,Pid,Port} -> + ?DBG("dummy_manager_start -> acknowledge received with" + "~n Port: ~p",[Port]), + {ok,Pid,Port}; + {'EXIT', Pid, Reason} -> + {error, Pid, Reason}; + O -> + ?LOG("dummy_manager_start -> received unknown message:" + "~n ~p",[O]), + await_dummy_manager_started(Pid) + end. + +dummy_manager_stop(Pid) -> + ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]), + Pid ! stop, + receive + {dummy_manager_stopping, Pid} -> + ?DBG("dummy_manager_stop -> acknowledge received",[]), + ok + after 10000 -> + ?ERR("dummy_manager_stop -> timeout",[]), + timeout + end. + +dummy_manager_send_trap2(Pid) -> + ?DBG("dummy_manager_send_trap2 -> entry",[]), + Pid ! {send_trap,testTrap2}. + +dummy_manager_await_trap2_ack() -> + ?DBG("dummy_manager_await_trap2 -> entry",[]), + receive + {received_trap,Trap} -> + ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]), + %% Note: + %% Without this sleep the v2_inform_i testcase failes! There + %% is no relation between these two test cases as far as I + %% able to figure out... + ?SLEEP(60000), + ok; + O -> + ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]), + ok + after 10000 -> + ?ERR("dummy_manager_await_trap2 -> timeout",[]), + timeout + end. + +dummy_manager_init(Parent,MA) -> + ?DBG("dummy_manager_init -> entry with" + "~n Parent: ~p" + "~n MA: ~p",[Parent,MA]), + {ok,S} = gen_udp:open(0,[{recbuf,65535}]), + ?DBG("dummy_manager_init -> S: ~p",[S]), + {ok,Port} = inet:port(S), + ?DBG("dummy_manager_init -> Port: ~p",[Port]), + Parent ! {dummy_manager_started,self(),Port}, + dummy_manager_loop(Parent,S,MA). + +dummy_manager_loop(P,S,MA) -> + ?LOG("dummy_manager_loop -> ready for receive",[]), + receive + {send_trap,Trap} -> + ?LOG("dummy_manager_loop -> received trap send request" + "~n Trap: ~p",[Trap]), + snmpa:send_trap(MA, Trap, "standard trap"), + dummy_manager_loop(P,S,MA); + {udp, _UdpId, Ip, UdpPort, Bytes} -> + ?LOG("dummy_manager_loop -> received upd message" + "~n from: ~p:~p" + "~n size: ~p", + [Ip, UdpPort, dummy_manager_message_sz(Bytes)]), + R = dummy_manager_handle_message(Bytes), + ?DBG("dummy_manager_loop -> R: ~p",[R]), + P ! R, + dummy_manager_loop(P,S,MA); + stop -> + ?DBG("dummy_manager_loop -> received stop request",[]), + P ! {dummy_manager_stopping, self()}, + gen_udp:close(S), + exit(normal); + O -> + ?LOG("dummy_manager_loop -> received unknown message:" + "~n ~p",[O]), + dummy_manager_loop(P,S,MA) + end. + +dummy_manager_message_sz(B) when is_binary(B) -> + size(B); +dummy_manager_message_sz(L) when is_list(L) -> + length(L); +dummy_manager_message_sz(_) -> + undefined. + +dummy_manager_handle_message(Bytes) -> + case (catch snmp_pdus:dec_message(Bytes)) of + {'EXIT',Reason} -> + ?ERR("dummy_manager_handle_message -> " + "failed decoding message only:~n ~p",[Reason]), + {error,Reason}; + M -> + ?DBG("dummy_manager_handle_message -> decoded message:" + "~n ~p",[M]), + {received_trap,M} + end. + + +api(suite) -> []; +api(Config) when is_list(Config) -> + ?P(api), + init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(api_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +api_2(X) -> ?P(api_2), api(X). + +api_3(X) -> ?P(api_3), api(X). + + +subagent(suite) -> []; +subagent(Config) when is_list(Config) -> + ?P(subagent), + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + try_test(load_test_sa), + + ?P1("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + + ?P1("Loading previous subagent mib in master and testing..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]), + try_test(load_test), + + ?P1("Unloading previous subagent mib in master and testing..."), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]), + try_test(unreg_test), + ?P1("Testing register subagent..."), + rpc:call(SaNode, snmp, register_subagent, + [MA, ?klas1, SA]), + try_test(load_test_sa), + + ?line stop_subagent(SA), + try_test(unreg_test). + +subagent_2(X) -> ?P(subagent_2), subagent(X). + +subagent_3(X) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(X, Condition), + %% </CONDITIONAL-SKIP> + + ?P(subagent_3), + subagent(X). + + +mnesia(suite) -> []; +mnesia(Config) when is_list(Config) -> + ?P(mnesia), + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?P1("Starting subagent with mnesia impl..."), + {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + try_test(big_test_2), + + ?P1("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA). + +mnesia_2(X) -> ?P(mnesia_2), mnesia(X). + +mnesia_3(X) -> ?P(mnesia_3), mnesia(X). + + +multiple_reqs(suite) -> + {req, [], {conf, init_mul, mul_cases(), finish_mul}}. + +mul_cases() -> + [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err]. + +multiple_reqs_2(suite) -> + {req, [], {conf, init_mul, mul_cases_2(), finish_mul}}. + +multiple_reqs_3(_X) -> + {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}. + + +mul_cases_2() -> + [mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2, mul_set_err_2]. + + +mul_cases_3() -> + [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3]. + + +init_mul(Config) when is_list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + [{mul_sub, SA} | Config]. + +finish_mul(Config) when is_list(Config) -> + init_case(Config), + + SA = ?config(mul_sub, Config), + + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA), + lists:keydelete(mul_sub, 1, Config). + +mul_get(suite) -> []; +mul_get(Config) when is_list(Config) -> + ?P(mul_get), + init_case(Config), + + ?P1("Testing multiple get..."), + try_test(do_mul_get). + +mul_get_2(X) -> ?P(mul_get_2), mul_get(X). + +mul_get_3(X) -> ?P(mul_get_3), mul_get(X). + + +mul_get_err(suite) -> []; +mul_get_err(Config) when is_list(Config) -> + ?P(mul_get_err), + init_case(Config), + + ?P1("Testing multiple get with error..."), + try_test(do_mul_get_err). + +mul_get_err_2(X) -> ?P(mul_get_err_2), mul_get_err(X). + +mul_get_err_3(X) -> ?P(mul_get_err_3), mul_get_err(X). + + +mul_next(suite) -> []; +mul_next(Config) when is_list(Config) -> + ?P(mul_next), + init_case(Config), + + ?P1("Testing multiple next..."), + try_test(do_mul_next). + +mul_next_2(X) -> ?P(mul_next_2), mul_next(X). + +mul_next_3(X) -> ?P(mul_next_3), mul_next(X). + + +mul_next_err(suite) -> []; +mul_next_err(Config) when is_list(Config) -> + ?P(mul_next_err), + init_case(Config), + + ?P1("Testing multiple next..."), + try_test(do_mul_next_err). + +mul_next_err_2(X) -> ?P(mul_next_err_2), mul_next_err(X). + +mul_next_err_3(X) -> ?P(mul_next_err_3), mul_next_err(X). + + +mul_set(suite) -> []; +mul_set(Config) when is_list(Config) -> + ?P(mul_set), + init_case(Config), + + ?P1("Testing multiple set..."), + try_test(do_mul_set). + +mul_set_2(X) -> ?P(mul_set_2), mul_set(X). + +mul_set_3(X) -> ?P(mul_set_3), mul_set(X). + + +mul_set_err(suite) -> []; +mul_set_err(Config) when is_list(Config) -> + ?P(mul_set_err), + init_case(Config), + + ?P1("Testing multiple set with error..."), + try_test(do_mul_set_err). + +mul_set_err_2(X) -> ?P(mul_set_err_2), mul_set_err(X). + +mul_set_err_3(X) -> ?P(mul_set_err_3), mul_set_err(X). + + +sa_register(suite) -> []; +sa_register(Config) when is_list(Config) -> + ?P(sa_register), + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?DBG("sa_register -> start subagent", []), + ?P1("start subagent..."), + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + + ?DBG("sa_register -> unregister subagent", []), + ?P1("Testing unregister subagent (2)..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + ?P1("Unloading Klas1..."), + ?DBG("sa_register -> unload mibs", []), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + + ?P1("Loading SA-MIB..."), + ?DBG("sa_register -> unload mibs", []), + snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]), + + ?P1("register subagent..."), + ?DBG("sa_register -> register subagent", []), + rpc:call(SaNode, snmp, register_subagent, [MA, ?sa, SA]), + + try_test(sa_mib), + + ?P1("stop subagent..."), + ?DBG("sa_register -> stop subagent", []), + ?line stop_subagent(SA). + +sa_register_2(X) -> ?P(sa_register_2), sa_register(X). + +sa_register_3(X) -> ?P(sa_register_3), sa_register(X). + + +v1_trap(suite) -> []; +v1_trap(Config) when is_list(Config) -> + ?P(v1_trap), + trap1(Config). + +trap1(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?P1("start subagent..."), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + ?P1("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?P1("load TestTrap & TestTrapv2..."), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + ?P1("Testing trap sending from master-agent..."), + try_test(ma_trap1, [MA]), + try_test(ma_trap2, [MA]), + try_test(ma_v2_2_v1_trap, [MA]), + try_test(ma_v2_2_v1_trap2, [MA]), + + ?P1("Testing trap sending from subagent..."), + try_test(sa_trap1, [SA]), + try_test(sa_trap2, [SA]), + try_test(sa_trap3, [SA]), + + ?P1("unload TestTrap & TestTrapv2..."), + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?P1("stop subagent..."), + ?line stop_subagent(SA). + +v2_trap(suite) -> []; +v2_trap(Config) when is_list(Config) -> + ?P(v2_trap), + trap2(Config). + +trap2(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?P1("start subagent..."), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + ?P1("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?P1("load TestTrap & TestTrapv2..."), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + ?P1("Testing trap sending from master-agent..."), + try_test(ma_v2_trap1, [MA]), + try_test(ma_v2_trap2, [MA]), + try_test(ma_v1_2_v2_trap, [MA]), + try_test(ma_v1_2_v2_trap2, [MA]), + + try_test(sa_mib), + + ?P1("Testing trap sending from subagent..."), + try_test(sa_v1_2_v2_trap1, [SA]), + try_test(sa_v1_2_v2_trap2, [SA]), + try_test(sa_v1_2_v2_trap3, [SA]), + + ?P1("unload TestTrap & TestTrapv2..."), + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?P1("stop subagent..."), + ?line stop_subagent(SA). + +v3_trap(suite) -> []; +v3_trap(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + ?P(v3_trap), + trap2(Config). + +v2_inform(suite) -> + {req, [], {conf, init_v2_inform, [v2_inform_i], finish_v2_inform}}. + +v3_inform(_X) -> + %% v2_inform(X). + {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}. + +init_v2_inform(Config) when is_list(Config) -> + _Dir = ?config(agent_dir, Config), + %% snmp_internal_mib:configure(Dir), + Config. + +init_v3_inform(X) -> + init_v2_inform(X). + +finish_v2_inform(Config) when is_list(Config) -> + _Dir = ?config(agent_dir, Config), + %% snmp_internal_mib:configure(Dir), + Config. + +finish_v3_inform(X) -> + finish_v2_inform(X). + + + +v2_inform_i(suite) -> []; +v2_inform_i(Config) when is_list(Config) -> + ?P(v2_inform_i), + inform_i(Config). + +inform_i(Config) -> + init_case(Config), + + MA = whereis(snmp_master_agent), + + ?P1("load TestTrap & TestTrapv2..."), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + ?P1("Testing inform sending from master agent... " + "~nNOTE! This test takes a few minutes (10) to complete."), + + try_test(ma_v2_inform1, [MA]), + try_test(ma_v2_inform2, [MA]), + try_test(ma_v2_inform3, [MA]), + + ?P1("unload TestTrap & TestTrapv2..."), + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"). + +v3_inform_i(X) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(X, Condition), + %% </CONDITIONAL-SKIP> + + ?P(v3_inform_i), + inform_i(X). + + +sa_error(suite) -> []; +sa_error(Config) when is_list(Config) -> + ?P(sa_error), + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?P1("load OLD-SNMPEA-MIB..."), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + ?P1("start subagent..."), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + ?P1("Testing sa bad value (is_set_ok)..."), + try_test(sa_errs_bad_value), + + ?P1("Testing sa gen err (set)..."), + try_test(sa_errs_gen_err), + + ?P1("Testing too big..."), + try_test(sa_too_big), + + ?P1("unload OLD-SNMPEA-MIB..."), + ?line unload_master("OLD-SNMPEA-MIB"), + + ?P1("stop subagent..."), + stop_subagent(SA). + +sa_error_2(X) -> + ?P(sa_error_2), + sa_error(X). + +sa_error_3(X) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(X, Condition), + %% </CONDITIONAL-SKIP> + + ?P(sa_error_3), + sa_error(X). + + +next_across_sa(suite) -> []; +next_across_sa(Config) when is_list(Config) -> + ?P(next_across_sa), + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?P1("start subagent (1)..."), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + ?P1("Loading another subagent mib (Klas1)..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]), + + ?P1("register subagent..."), + rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]), + + ?P1("Load test subagent..."), + try_test(load_test_sa), + + ?P1("Testing next across subagent (endOfMibView from SA)..."), + try_test(next_across_sa), + + ?P1("Unloading mib (Klas1)"), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + ?P1("Starting another subagent (2) "), + ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"), + ?P1("Testing next across subagent (wrong prefix from SA)..."), + try_test(next_across_sa), + + ?P1("stop subagent (1)..."), + stop_subagent(SA), + + ?P1("stop subagent (2)..."), + stop_subagent(SA2). + +next_across_sa_2(X) -> + ?P(next_across_sa_2), + next_across_sa(X). + +next_across_sa_3(X) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(X, Condition), + %% </CONDITIONAL-SKIP> + + ?P(next_across_sa_3), + next_across_sa(X). + + +undo(suite) -> []; +undo(Config) when is_list(Config) -> + ?P(undo), + {SaNode, _MgrNode, MibDir} = init_case(Config), + + MA = whereis(snmp_master_agent), + + ?P1("start subagent (1)..."), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + ?P1("Load Klas3 & Klas4..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]), + + ?P1("Testing undo phase at master agent..."), + try_test(undo_test), + try_test(api_test2), + + ?P1("Unload Klas3..."), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]), + + ?P1("Testing bad return values from instrum. funcs..."), + try_test(bad_return), + + ?P1("Unload Klas4..."), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]), + + ?P1("Testing undo phase at subagent..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]), + ?line ok = snmpa:register_subagent(MA, ?klas3, SA), + ?line ok = snmpa:register_subagent(MA, ?klas4, SA), + try_test(undo_test), + try_test(api_test3), + + ?P1("Testing undo phase across master/subagents..."), + try_test(undo_test), + try_test(api_test3), + + ?P1("stop subagent..."), + stop_subagent(SA). + +undo_2(X) -> + ?P(undo_2), + undo(X). + +undo_3(X) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(X, Condition), + %% </CONDITIONAL-SKIP> + + ?P(undo_3), + undo(X). + +%% Req. Test2 +v1_processing(suite) -> []; +v1_processing(Config) when is_list(Config) -> + ?P(v1_processing), + ?DBG("v1_processing -> entry", []), + init_case(Config), + + ?P1("Load Test2..."), + ?line load_master("Test2"), + + try_test(v1_proc), + + ?P1("Unload Test2..."), + ?line unload_master("Test2"). + +%% Req. Test2 +v2_processing(suite) -> []; +v2_processing(Config) when is_list(Config) -> + ?P(v2_processing), + init_case(Config), + + ?P1("Load Test2..."), + ?line load_master("Test2"), + + try_test(v2_proc), + + ?P1("Unload Test2..."), + ?line unload_master("Test2"). + +%% Req. Test2 +v3_processing(suite) -> []; +v3_processing(Config) when is_list(Config) -> + ?P(v3_processing), + init_case(Config), + + ?P1("Load Test2..."), + ?line load_master("Test2"), + + try_test(v2_proc), % same as v2! + + ?P1("Unload Test2..."), + ?line unload_master("Test2"). + + +%% We'll try get/set/trap and inform for all the auth & priv protocols. +%% For informs, the mgr is auth-engine. The agent has to sync. This is +%% accomplished by the first inform sent. That one will generate a +%% report, which makes it in sync. The notification-generating +%% application times out, and send again. This time it'll work. +v3_security(suite) -> + [ + v3_crypto_basic, + v3_md5_auth, + v3_sha_auth, + v3_des_priv + ]. + +v3_crypto_basic(suite) -> []; +v3_crypto_basic(_Config) -> + ?P(v3_crypto_basic), + EID = [0,0,0,0,0,0,0,0,0,0,0,2], + %% From rfc2274 appendix A.3.1 + ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID), + ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f, + 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] = + KMd5_1, + %% From rfc2274 appendix A.3.2 + ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID), + ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23, + 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] = + KSHA_1, + %% From rfc2274, appendix A.5.1 + ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9, + 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] = + snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + %% From rfc2274, appendix A.5.2 + ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4, + 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db, + 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + KSHA_1t = lists:sublist(KSHA_1, 16), + KSHA_2t = lists:sublist(KSHA_2, 16), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b, + 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + + %% Try with correct random + ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2), + ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1), + ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2), + ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2), + ok. + + + +v3_md5_auth(suite) -> []; +v3_md5_auth(Config) when is_list(Config) -> + ?P(v3_md5_auth), + init_case(Config), + + ?P1("Testing MD5 authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authMD5"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_sha_auth(suite) -> []; +v3_sha_auth(Config) when is_list(Config) -> + ?P(v3_sha_auth), + init_case(Config), + + ?P1("Testing SHA authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authSHA"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_des_priv(suite) -> []; +v3_des_priv(Config) when is_list(Config) -> + ?P(v3_des_priv), + init_case(Config), + + ?P1("Testing DES encryption...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + snmp_user_based_sm_mib:usmUserTable(print), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +%% Make sure mgr is in sync with agent +v3_sync(Funcs) -> + ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]), + g([[sysDescr, 0]]), + expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]), + g([[sysDescr, 0]]), + expect(433, [{[sysDescr,0], any}]), + lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs). + +v3_inform_sync(MA) -> + ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, + "standard inform", []), + %% Make sure agent is in sync with mgr... + ?DBG("v3_sync -> wait some time: ",[]), + ?SLEEP(20000), % more than 1500*10 in target_addr.conf + ?DBG("v3_sync -> await response",[]), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]). + + +v2_caps(suite) -> []; +v2_caps(Config) when is_list(Config) -> + ?P(v2_caps), + init_case(Config), + + try_test(v2_caps_i, [node()]). + +v2_caps_3(X) -> ?P(v2_caps_3), v2_caps(X). + + +v2_caps_i(Node) -> + ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]), + g([[sysORID, Idx], [sysORDescr, Idx]]), + ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]}, + {[sysORDescr, Idx], "test cap"}]), + ?line rpc:call(Node, snmp, del_agent_caps, [Idx]), + g([[sysORID, Idx]]), + ?line expect(2, [{[sysORID, Idx], noSuchInstance}]). + + +%% Req. Test2 +v1_proc() -> + ?DBG("v1_proc -> entry", []), + %% According to RFC1157. + %% Template: <Section>:<list no> + v1_get_p(), + v1_get_next_p(), + v1_set_p(). + + +v1_get_p() -> + %% 4.1.2:1 + g([[test2]]), + ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]), + g([[tDescr]]), + ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]), + g([[tDescr2,0]]), + ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]), + g([[tDescr3,0]]), + ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]), + g([[tDescr4,0]]), + ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'}, + {[tDescr,0], 'NULL'}]), + g([[sysDescr,3]]), + ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]), + + %% 4.1.2:2 + g([[tTable]]), + ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]), + g([[tEntry]]), + ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]), + + %% 4.1.2:3 + g([[tTooBig, 0]]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.2:4 + g([[tGenErr1, 0]]), + ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]). + + +v1_get_next_p() -> + %% 4.1.3:1 + gn([[1,3,7,1]]), + ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]), + gn([[tDescr2]]), + ?line expect(11, tooBig, 0, any), + + %% 4.1.3:2 + gn([[tTooBig]]), + io:format("We currently don't handle tooBig correct!!!\n"), +% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]), + ?line expect(20, tooBig, 0, any), + + %% 4.1.3:3 + gn([[tGenErr1]]), +% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]), + ?line expect(40, genErr, 1, any), + gn([[tGenErr2]]), +% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]), + ?line expect(41, genErr, 1, any), + gn([[sysDescr], [tGenErr3]]), +% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'}, +% {[tGenErr3], 'NULL'}]). + ?line expect(42, genErr, 2, any). + +v1_set_p() -> + %% 4.1.5:1 + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]), + s([{[tDescr3], s, "noSuchObject"}]), + ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]), + s([{[tDescr3,1], s, "noSuchInstance"}]), + ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]), + s([{[tDescr2,0], s, "inconsistentName"}]), + ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]), + + %% 4.1.5:2 + s([{[tDescr2, 0], i, 4}]), + ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.1.5:3 + %% The standard is quite incorrect here. The resp pdu was too big. In + %% the resp pdu, we have the original vbs. In the tooBig pdu we still + %% have to original vbs => the tooBig pdu is too big as well!!! It + %% may not get it to the manager, unless the agent uses 'NULL' instead + %% of the std-like original value. + s([{[tTooBig, 0], s, ?tooBigStr}]), + %% according to std: +% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.5:4 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]), + s([{[tDescr2, 0], s, "commit_fail"}]), + ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]). + +%% Req. Test2 +v2_proc() -> + %% According to RFC1905. + %% Template: <Section>:<list no> + ?DBG("v2_proc -> entry",[]), + v2_get_p(), + v2_get_next_p(), + v2_get_bulk_p(), + v2_set_p(). + +v2_get_p() -> + %% 4.2.1:2 + ?DBG("v2_get_p -> entry",[]), + g([[test2]]), + ?line expect(10, [{[test2], noSuchObject}]), + g([[tDescr]]), + ?line expect(11, [{[tDescr], noSuchObject}]), + g([[tDescr4,0]]), + ?line expect(12, [{[tDescr4,0], noSuchObject}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}, + {[tDescr,0], noSuchObject}]), + g([[tTable]]), + ?line expect(14, [{[tTable], noSuchObject}]), + g([[tEntry]]), + ?line expect(15, [{[tEntry], noSuchObject}]), + + %% 4.2.1:3 + g([[tDescr2,0]]), %% instrum ret noSuchName!!! + ?line expect(20, [{[tDescr2,0], noSuchInstance}]), + g([[tDescr3,0]]), + ?line expect(21, [{[tDescr3,0], noSuchInstance}]), + g([[sysDescr,3]]), + ?line expect(22, [{[sysDescr, 3], noSuchInstance}]), + g([[tIndex,1]]), + ?line expect(23, [{[tIndex, 1], noSuchInstance}]), + + %% 4.2.1 - any other error: genErr + g([[tGenErr1, 0]]), + ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]), + + %% 4.2.1 - tooBig + g([[tTooBig, 0]]), + ?line expect(40, tooBig, 0, []). + + +v2_get_next_p() -> + %% 4.2.2:2 + ?DBG("v2_get_next_p -> entry",[]), + gn([[1,3,7,1]]), + ?line expect(10, [{[1,3,7,1], endOfMibView}]), + gn([[sysDescr], [1,3,7,1]]), + ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gn([[tCnt2, 1]]), + ?line expect(12, [{[tCnt2,2], 100}]), + gn([[tCnt2, 2]]), + ?line expect(12, [{[tCnt2,2], endOfMibView}]), + + %% 4.2.2 - any other error: genErr + gn([[tGenErr1]]), + ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]), + gn([[tGenErr2]]), + ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]), + gn([[sysDescr], [tGenErr3]]), + ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'}, + {[tGenErr3], 'NULL'}]), + + %% 4.2.2 - tooBig + gn([[tTooBig]]), + ?line expect(20, tooBig, 0, []). + +v2_get_bulk_p() -> + %% 4.2.3 + ?DBG("v2_get_bulk_p -> entry",[]), + gb(1, 1, []), + ?line expect(10, []), + gb(-1, 1, []), + ?line expect(11, []), + gb(-1, -1, []), + ?line expect(12, []), + gb(-1, -1, []), + ?line expect(13, []), + gb(2, 0, [[sysDescr], [1,3,7,1]]), + ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(1, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(0, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]), + ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]), + ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[sysDescr, 0], "Erlang SNMP agent"}]), + + gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig. + ?line expect(19, []), + + gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]), + ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'}, + {[sysObjectID], 'NULL'}, + {[tGenErr1], 'NULL'}, + {[sysDescr], 'NULL'}]), + gb(0, 2, [[tCnt2, 1]]), + ?line expect(21, [{[tCnt2,2], 100}, + {[tCnt2,2], endOfMibView}]). + + +v2_set_p() -> + %% 4.2.5:1 + ?DBG("v2_set_p -> entry",[]), + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]), + + %% 4.2.5:2 + s([{[1,3,6,1,0], s, "noSuchObject"}]), + ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]), + + %% 4.2.5:3 + s([{[tDescr2, 0], i, 4}]), + ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.2.5:4 + s([{[tStr, 0], s, ""}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]), + s([{[tStr, 0], s, "12345"}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]), + + %% 4.2.5:5 - N/A + + %% 4.2.5:6 + s([{[tInt1, 0], i, 0}]), + ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]), + s([{[tInt1, 0], i, 5}]), + ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]), + s([{[tInt2, 0], i, 0}]), + ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]), + s([{[tInt2, 0], i, 5}]), + ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]), + s([{[tInt3, 0], i, 5}]), + ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]), + + %% 4.2.5:7 + s([{[tDescrX, 1, 1], s, "noCreation"}]), + ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]), + + %% 4.2.5:8 + s([{[tDescrX, 1, 2], s, "inconsistentName"}]), + ?line expect(80, inconsistentName, 1, + [{[tDescrX, 1, 2], "inconsistentName"}]), + + %% 4.2.5:9 + s([{[tCnt, 1, 2], i, 5}]), + ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]), + + %% 4.2.5:10 + s([{[tDescr2,0], s, "inconsistentValue"}]), + ?line expect(100, inconsistentValue, 1, + [{[tDescr2,0], "inconsistentValue"}]), + + %% 4.2.5:11 + s([{[tDescr2,0], s, "resourceUnavailable"}]), + ?line expect(110, resourceUnavailable, 1, + [{[tDescr2,0],"resourceUnavailable"}]), + + %% 4.2.5:12 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]). + + %% commitFailed and undoFailed is tested by the 'undo' case. + + +%% Req. OLD-SNMPEA-MIB +table_test() -> + io:format("Testing simple get, next and set on communityTable...~n"), +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. + Key1c3 = [intCommunityViewIndex,get(mip),is("public")], + Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")], + Key1c4 = [intCommunityAccess,get(mip),is("public")], + EndKey = [intCommunityEntry,[9],get(mip),is("public")], + gn([[intCommunityEntry]]), + ?line expect(7, [{Key1c3, 2}]), + gn([[intCommunityTable]]), + ?line expect(71, [{Key1c3, 2}]), + gn([[community]]), + ?line expect(72, [{Key1c3, 2}]), + gn([[otpSnmpeaMIB]]), + ?line expect(73, [{Key1c3, 2}]), + gn([[ericsson]]), + ?line expect(74, [{Key1c3, 2}]), + gn([Key1c3]), + ?line expect(8, [{Key2c3, 2}]), + gn([Key2c3]), + ?line expect(9, [{Key1c4, 2}]), + gn([EndKey]), + AgentIp = [intAgentIpAddress,0], + ?line expect(10, [{AgentIp, any}]), + g([Key1c3]), + ?line expect(11, [{Key1c3, 2}]), + g([EndKey]), + ?line ?v1_2(expect(12, noSuchName, 1, any), + expect(12, [{EndKey, noSuchObject}])), + + io:format("Testing row creation/deletion on communityTable...~n"), + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + s([{NewKeyc5, ?createAndGo}]), + ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any), + s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]), + ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]), + g([NewKeyc4]), + ?line expect(16, [{NewKeyc4, 2}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(17, [{NewKeyc5, ?destroy}]), + s([{NewKeyc4, 2}]), + ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]), + s([{NewKeyc5, ?createAndWait}]), + ?line expect(19, [{NewKeyc5, ?createAndWait}]), + g([NewKeyc5]), + ?line expect(20, [{NewKeyc5, ?notReady}]), + s([{NewKeyc4, 2}]), + ?line expect(21, [{NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(22, [{NewKeyc5, ?notReady}]), + s([{NewKeyc3, 2}]), + ?line expect(23, [{NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(24, [{NewKeyc5, ?notInService}]), + s([{NewKeyc5, ?active}]), + ?line expect(25, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(26, [{NewKeyc5, ?destroy}]), + s([{NewKeyc3, 3}]), + ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]), + otp_1128(). + +%% Req. system group +simple_standard_test() -> + ?DBG("simple_standard_test -> entry",[]), + gn([[1,1]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3]]), + ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6]]), + ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1]]), + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2]]), + ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1]]), + ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1,1]]), + ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[sysDescr]]), + ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr,0]]), + ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr]]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{[sysDescr], noSuchObject}])), + g([[1,6,7,0]]), + ?line ?v1_2(expect(41, noSuchName, 1, any), + expect(3, [{[1,6,7,0], noSuchObject}])), + gn([[1,13]]), + ?line ?v1_2(expect(4, noSuchName,1, any), + expect(4, [{[1,13], endOfMibView}])), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + g([[sysLocation, 0]]), + ?line expect(6, [{[sysLocation, 0], "new_value"}]), + io:format("Testing noSuchName and badValue...~n"), + s([{[sysServices,0], 3}]), + ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any), + s([{[sysLocation, 0], i, 3}]), + ?line expect(62, ?v1_2(badValue, wrongType), 1, any), + ?DBG("simple_standard_test -> done",[]), + ok. + +%% This is run in the agent node +db_notify_client(suite) -> []; +db_notify_client(Config) when is_list(Config) -> + ?P(db_notify_client), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("db_notify_client -> case initiated: " + "~n SaNode: ~p" + "~n MgrNode: ~p" + "~n MibDir: ~p", [SaNode, MgrNode, MibDir]), + ?DBG("db_notify_client -> maximize verbosity", []), + snmpa_local_db:verbosity(trace), + Self = self(), + ?DBG("db_notify_client -> register self (~p) notify client", [Self]), + snmpa_local_db:register_notify_client(self(),?MODULE), + + %% This call (to the manager) will issue to set operations, so + %% we expect to receive to notify(insert) calls. + try_test(db_notify_client_test), + + ?DBG("db_notify_client -> await first notify",[]), + receive + {db_notify_test_reply, insert} -> + ?DBG("db_notify_client -> first notify received",[]), + ok + after 10000 -> + ?FAIL({timeout, waiting_for_first_event}) + end, + + ?DBG("db_notify_client -> await second notify",[]), + receive + {db_notify_test_reply, insert} -> + ?DBG("db_notify_client -> second notify received",[]), + ok + after 10000 -> + ?FAIL({timeout, waiting_for_second_event}) + end, + + ?DBG("db_notify_client -> unregister self (~p) notify client", [Self]), + snmpa_local_db:unregister_notify_client(self()), + ?DBG("db_notify_client -> minimize verbosity", []), + snmpa_local_db:verbosity(silence), + + ?DBG("db_notify_client -> done", []), + ok. + + +%% This is run in the manager node +db_notify_client_test() -> + ?DBG("set first new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + + ?DBG("set second new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]). + +notify(Pid, What) -> + ?DBG("notify(~p,~p) -> called",[Pid,What]), + Pid ! {db_notify_test_reply, What}. + + +%% Req: system group, OLD-SNMPEA-MIB, Klas1 +big_test() -> + %% put(sname, {?MODULE, big_test}), + %% put(verbosity, trace), + + ?DBG("big_test -> testing simple next/get/set @ master agent...",[]), + simple_standard_test(), + + ?DBG("big_test -> testing simple next/get/set @ subagent...",[]), + gn([[klas1]]), + ?line expect(1, [{[fname,0], ""}]), + g([[fname,0]]), + ?line expect(2, [{[fname,0], ""}]), + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[fname,0]]), + ?line expect(4, [{[fname,0], "test set"}]), + + ?DBG("big_test -> " + "testing next from last instance in master to subagent...",[]), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname,0], "test set"}]), + s([{[fname,0], s, ""}]), + ?line expect(52, [{[fname,0], ""}]), + + table_test(), + + ?DBG("big_test -> adding one row in subagent table",[]), + _FTab = [friendsEntry], + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {[friendsEntry, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [friendsEntry, [3, 3]]]), + ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?active}]), + s([{[friendsEntry, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]), + + otp_1131(), + + ?DBG("big_test -> adding two rows in subagent table with special INDEX", + []), + s([{[kompissEntry, [1, 3]], s, "kompis3"}, + {[kompissEntry, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?createAndGo}]), + g([[kompissEntry, [1, 3]], + [kompissEntry, [2, 3]]]), + ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + gn([[kompissEntry, [1]], + [kompissEntry, [2]]]), + ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + s([{[kompissEntry, [1, 2]], s, "kompis3"}, + {[kompissEntry, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?createAndGo}]), + gn([[kompissEntry, [1, 1]], + [kompissEntry, [2, 1]]]), + ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?active}]), + s([{[kompissEntry, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]), + s([{[kompissEntry, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]), + ?DBG("big_test -> done",[]), + ok. + +%% Req. system group, Klas2, OLD-SNMPEA-MIB +big_test_2() -> + ?P1("Testing simple next/get/set @ master agent (2)..."), + simple_standard_test(), + + ?P1("Testing simple next/get/set @ subagent (2)..."), + gn([[klas2]]), + ?line expect(1, [{[fname2,0], ""}]), + g([[fname2,0]]), + ?line expect(2, [{[fname2,0], ""}]), + s([{[fname2,0], s, "test set"}]), + ?line expect(3, [{[fname2,0], "test set"}]), + g([[fname2,0]]), + ?line expect(4, [{[fname2,0], "test set"}]), + + otp_1298(), + + ?P1("Testing next from last object in master to subagent (2)..."), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname2,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname2,0], "test set"}]), + + table_test(), + + ?P1("Adding one row in subagent table (2)"), + _FTab = [friendsEntry2], + s([{[friendsEntry2, [2, 3]], s, "kompis3"}, + {[friendsEntry2, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?createAndGo}]), + g([[friendsEntry2, [2, 3]], + [friendsEntry2, [3, 3]]]), + ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?active}]), + s([{[friendsEntry2, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]), + + ?P1("Adding two rows in subagent table with special INDEX (2)"), + s([{[kompissEntry2, [1, 3]], s, "kompis3"}, + {[kompissEntry2, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?createAndGo}]), + g([[kompissEntry2, [1, 3]], + [kompissEntry2, [2, 3]]]), + ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + gn([[kompissEntry2, [1]], + [kompissEntry2, [2]]]), + ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + s([{[kompissEntry2, [1, 2]], s, "kompis3"}, + {[kompissEntry2, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?createAndGo}]), + gn([[kompissEntry2, [1, 1]], + [kompissEntry2, [2, 1]]]), + ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?active}]), + s([{[kompissEntry2, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]), + s([{[kompissEntry2, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]), + ok. + +%% Req. Test1 +multi_threaded_test() -> + ?P1("Testing multi threaded agent..."), + g([[multiStr,0]]), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(1, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "pelle"}]), + ?line expect(2, [{[sysLocation, 0], "pelle"}]), + Pid ! continue, + ?line expect(3, [{[multiStr,0], "ok"}]), + + s([{[multiStr, 0], s, "block"}]), + Pid2 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(4, [{[sysUpTime,0], any}]), + g([[multiStr,0]]), + Pid3 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(5, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "kalle"}]), + Pid3 ! continue, + ?line expect(6, [{[multiStr,0], "ok"}]), + Pid2 ! continue, + ?line expect(7, [{[multiStr,0], "block"}]), + ?line expect(8, [{[sysLocation,0], "kalle"}]). + +%% Req. Test1, TestTrapv2 +mt_trap_test(MA) -> + ?P1("Testing trap-sending with multi threaded agent..."), + ?DBG("mt_trap_test(01) -> issue testTrapv22 (standard trap)", []), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?DBG("mt_trap_test(02) -> await v2trap", []), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + ?DBG("mt_trap_test(03) -> issue mtTrap (standard trap)", []), + snmpa:send_trap(MA, mtTrap, "standard trap"), + Pid = get_multi_pid(), + ?DBG("mt_trap_test(04) -> multi pid: ~p. Now request sysUpTime...", [Pid]), + g([[sysUpTime,0]]), + + %% Previously (before OTP-6784) this was done at 09 below + %% when the test1:multiStr was actually executed by the + %% worker-process, but as of 4.9.4, this is now executed + %% my the master_agent-process... + ?DBG("mt_trap_test(05) -> send continue to multi-pid", []), + Pid ! continue, + + ?DBG("mt_trap_test(06) -> await sysUpTime", []), + ?line expect(2, [{[sysUpTime,0], any}]), + ?DBG("mt_trap_test(07) -> issue testTrapv22 (standard trap)", []), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?DBG("mt_trap_test(08) -> await v2trap", []), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + %% ?DBG("mt_trap_test(09) -> send continue to multi-pid", []), + %% Pid ! continue, + + ?DBG("mt_trap_test(10) -> await v2trap", []), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [2]}, + {[multiStr,0], "ok"}]), + ?DBG("mt_trap_test(11) -> done", []), + ok. + + +get_multi_pid() -> + get_multi_pid(10). +get_multi_pid(0) -> + ?line ?FAIL(no_global_name); +get_multi_pid(N) -> + ?SLEEP(1000), + case global:whereis_name(snmp_multi_tester) of + Pid when is_pid(Pid) -> Pid; + _ -> get_multi_pid(N-1) + end. + +%% Req. Test1 +types_v2_test() -> + ?P1("Testing v2 types..."), + + s([{[bits1,0], 2#10}]), + ?line expect(1, [{[bits1,0], ?str(2#10)}]), + g([[bits1,0]]), + ?line expect(2, [{[bits1,0], ?str(2#101)}]), + + s([{[bits2,0], 2#11000000110}]), + ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]), + g([[bits2,0]]), + ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]), + + g([[bits3,0]]), + ?line expect(50, genErr, 1, any), + + g([[bits4,0]]), + ?line expect(51, genErr, 1, any), + + s([{[bits1,0], s, [2#10]}]), + ?line expect(6, ?v1_2(badValue, wrongValue), 1, any), + + s([{[bits2,0], 2#11001001101010011}]), + ?line expect(7, ?v1_2(badValue, wrongValue), 1, any). + + +%% Req. Test1 +implied_test(MA) -> + ?LOG("implied_test -> start",[]), + ?P1("Testing IMPLIED..."), + + snmpa:verbosity(MA,trace), + snmpa:verbosity(MA,trace), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = "apa", + Idx2 = "qq", + ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]), + ?line expect(1, [{[testStatus, Idx1], ?createAndGo}, + {[testDescr, Idx1], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]), + ?line expect(2, [{[testStatus, Idx2], ?createAndGo}, + {[testDescr, Idx2], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr)",[]), + gn([[testDescr]]), + ?line expect(3, [{[testDescr,Idx1], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr) of row 1",[]), + gn([[testDescr,Idx1]]), + ?line expect(4, [{[testDescr,Idx2], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?destroy}]), + ?line expect(5, [{[testStatus, Idx1], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?destroy}]), + ?line expect(6, [{[testStatus, Idx2], ?destroy}]), + + %% Try the same in other table + Idx3 = [1, "apa"], + Idx4 = [1, "qq"], + ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]), + ?line expect(1, [{[testStatus2, Idx3], ?createAndGo}, + {[testDescr2, Idx3], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]), + ?line expect(2, [{[testStatus2, Idx4], ?createAndGo}, + {[testDescr2, Idx4], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr2)",[]), + gn([[testDescr2]]), + ?line expect(3, [{[testDescr2,Idx3], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr2) of row 1",[]), + gn([[testDescr2,Idx3]]), + ?line expect(4, [{[testDescr2,Idx4], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?destroy}]), + ?line expect(5, [{[testStatus2, Idx3], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?destroy}]), + ?line expect(6, [{[testStatus2, Idx4], ?destroy}]), + + snmpa:verbosity(MA,log), + + ?LOG("implied_test -> done",[]). + + + +%% Req. Test1 +sparse_table_test() -> + ?P1("Testing sparse table..."), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + s([{[sparseStatus, Idx1], i, ?createAndGo}, + {[sparseDescr, Idx1], s, "row 1"}]), + ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo}, + {[sparseDescr, Idx1], "row 1"}]), + s([{[sparseStatus, Idx2], i, ?createAndGo}, + {[sparseDescr, Idx2], s, "row 2"}]), + ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo}, + {[sparseDescr, Idx2], "row 2"}]), + ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2], + [sparseStatus,Idx1], [sparseStatus,Idx2]]), + gb(0,5,[[sparseIndex]])), + ?line expect(3, [{[sparseDescr,Idx1], "row 1"}, + {[sparseDescr,Idx2], "row 2"}, + {[sparseStatus,Idx1], ?active}, + {[sparseStatus,Idx2], ?active}, + {[sparseStr,0], "slut"}]), + % Delete the rows + s([{[sparseStatus, Idx1], i, ?destroy}]), + ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]), + s([{[sparseStatus, Idx2], i, ?destroy}]), + ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]). + + +%% Req. Test1 +cnt_64_test(MA) -> + ?LOG("start cnt64 test (~p)",[MA]), + snmpa:verbosity(MA, trace), + ?LOG("start cnt64 test",[]), + ?P1("Testing Counter64, and at the same time, " + "RowStatus is not last column"), + + ?DBG("get cnt64",[]), + g([[cnt64,0]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(1, noSuchName, 1, any), + expect(1, [{[cnt64,0],18446744073709551615}])), + ?DBG("get-next cnt64",[]), + gn([[cnt64]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]), + expect(2, [{[cnt64,0],18446744073709551615}])), + ?DBG("send cntTrap",[]), + snmpa:send_trap(MA,cntTrap,"standard trap",[ + {sysContact, "pelle"}, + {cnt64, 10}, + {sysLocation, "here"} + ]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"}, + {[sysLocation,0], "here"}]), + expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [1]}, + {[sysContact,0], "pelle"}, + {[cnt64,0], 10}, + {[sysLocation,0], "here"}])), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + ?DBG("create row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]), + ?DBG("create row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]), + + ?DBG("get-next (cntIndex)",[]), + gn([[cntIndex]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]), + expect(3, [{[cntCnt,Idx1], 0}])), + % Delete the rows + ?DBG("delete row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(4, [{[cntStatus, Idx1], ?destroy}]), + ?DBG("delete row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(5, [{[cntStatus, Idx2], ?destroy}]), + catch snmpa:verbosity(MA,log), + ?DBG("done",[]), + ok. + +%% Req. Test1 +opaque_test() -> + ?P1("Testing Opaque datatype..."), + g([[opaqueObj,0]]), + ?line expect(1, [{[opaqueObj,0], "opaque-data"}]). + +%% Req. OLD-SNMPEA-MIB +api_test(MaNode) -> + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [intAgentIpAddress]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, + oid_to_name, [OID]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [[1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, + int_to_enum, ['RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]), + ?line case snmp:date_and_time() of + List when is_list(List), length(List) == 8 -> ok; + List when is_list(List), length(List) == 11 -> ok + end. + +%% Req. Klas3 +api_test2() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]), + g([[fname4,0]]), + ?line expect(2, [{[fname4,0], 1}]). + +api_test3() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]). + + +unreg_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[snmpInPkts, 0], any}]). + +load_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[fname,0], ""}]). + +%% Req. Klas1 +load_test_sa() -> + gn([[?v1_2(sysServices,sysORLastChange), 0]]), + ?line expect(1, [{[fname,0], any}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_get() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0], Key1c4, [fname,0],Key1c3, + [sysName,0]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,0], "test"}]), + g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]), + ?line ?v1_2(expect(2, noSuchName, [1,4], any), + expect(2, [{[1,3,7,1], noSuchObject}, + {Key1c4, 2}, + {[sysDescr,0], "Erlang SNMP agent"}, + {[1,3,7,2], noSuchObject}, + {Key1c3, 2}, + {[sysDescr,0], "Erlang SNMP agent"}])). + +%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3. +do_mul_get_err() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]), + ?line ?v1_2(expect(1, noSuchName, 5, any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,2], noSuchInstance}])), + g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname3,0], noSuchObject}, + {Key1c3, 2}, + {[sysName,1], noSuchInstance}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, {[fname,0], "test set"}, + {Key1c3, 2}, {[sysName,0], "test"}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next_err() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[1,3,6,999], endOfMibView}, + {[fname,0], "test set"}, + {[1,3,90], endOfMibView}, + {Key1c3, 2}, + {[sysName,0], "test"}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set() -> + ?P1("Adding one row in subagent table, and one in master table"), + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [sysLocation,0], + [friendsEntry, [3, 3]]]), + ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"}, + {[sysLocation,0], "new_value"}, + {[friendsEntry, [3, 3]], ?active}]), + g([NewKeyc4]), + ?line expect(3, [{NewKeyc4, 2}]), + s([{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]), + ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + ?P1("Adding one row in subagent table, and one in master table"), + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {NewKeyc3, 2}, + {[sysUpTime,0], 45}, % sysUpTime (readOnly) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any), + g([[friendsEntry, [2, 3]]]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])), + g([NewKeyc4]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB +sa_mib() -> + g([[sa, [2,0]]]), + ?line expect(1, [{[sa, [2,0]], 3}]), + s([{[sa, [1,0]], s, "sa_test"}]), + ?line expect(2, [{[sa, [1,0]], "sa_test"}]). + +ma_trap1(MA) -> + snmpa:send_trap(MA, testTrap2, "standard trap"), + ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]), + snmpa:send_trap(MA, testTrap1, "standard trap"), + ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]). + +ma_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap2(MA) -> + snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1}, + {ifAdminStatus, [1], 1}, + {ifOperStatus, [1], 2}]), + ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}]). + +sa_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]], + "pelle"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}]). + +ma_v2_trap1(MA) -> + ?DBG("ma_v2_traps -> entry with MA = ~p => " + "send standard trap: testTrapv22",[MA]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]), + snmpa:send_trap(MA, testTrapv21, "standard trap"), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmp ++ [1]}]). + +ma_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}]). + +%% Note: This test case takes a while... actually a couple of minutes. +ma_v2_inform1(MA) -> + ?DBG("ma_v2_inform1 -> entry with" + "~n MA = ~p => " + "~n send notification: testTrapv22", [MA]), + + CmdExpectInform = + fun(No, Response) -> + expect(No, + {inform, Response}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]) + end, + + CmdExp = + fun(ok) -> + ok; + ({ok, Val}) -> + ?DBG("ma_v2_inform -> [cmd2] Val: ~p", [Val]), + ok; + ({error, Id, Extra}) -> + {error, {unexpected, Id, Extra}}; + (Error) -> + Error + end, + + Cmd01 = + fun() -> + snmpa:send_notification(MA, testTrapv22, no_receiver, + "standard inform", []), + ok + end, + Cmd02 = + fun() -> + Res = CmdExpectInform(1, true), + CmdExp(Res) + end, + + Tag03 = tag11, + Cmd03 = + fun() -> + snmpa:send_notification(MA, testTrapv22, {Tag03, self()}, + "standard inform", []), + ok + end, + Cmd04 = + fun() -> + Res = CmdExpectInform(2, true), + CmdExp(Res) + end, + CmdSnmpTargets = + fun(T) -> + receive + {snmp_targets, T, [Addr]} -> + ?DBG("ma_v2_inform1 -> " + "received expected snmp_targets " + "~n with receiver: ~p",[Addr]), + ok; + {snmp_targets, T, Addrs} -> + ?ERR("ma_v2_inform1 -> " + "received unexpected snmp_targets" + "~n with receivers: ~n ~p",[Addrs]), + {error, {bad_addrs, Addrs}} + after + 5000 -> + ?ERR("ma_v2_inform1 -> " + "timeout awaiting snmp_targets [~w]",[T]), + {error, snmp_targets_timeout} + end + end, + Cmd05 = fun() -> CmdSnmpTargets(Tag03) end, + Cmd06 = + fun() -> + receive + {snmp_notification, Tag03, {got_response, Addr}} -> + ?DBG("ma_v2_inform1 -> " + "received expected snmp_notification " + "[with manager response] from: ~n ~p",[Addr]), + ok; + {snmp_notification, Tag03, {no_response, Addr}} -> + ?ERR("ma_v2_inform1 -> " + "received unexpected snmp_notification " + "[without manager response] from: ~n ~p", + [Addr]), + {error, no_response} + after + 20000 -> + ?ERR("ma_v2_inform1 -> " + "timeout awaiting snmp_notification [~p]", + [Tag03]), + {error, snmp_notification_timeout} + end + end, + + Tag07 = tag12, + Cmd07 = + fun() -> + snmpa:send_notification(MA, testTrapv22, {Tag07, self()}, + "standard inform", []), + ok + end, + Cmd08 = + fun() -> + Res = CmdExpectInform(3, false), + CmdExp(Res) + end, + Cmd09 = + fun() -> + CmdSnmpTargets(Tag07) + end, + Cmd10 = + fun() -> + receive + {snmp_notification, Tag07, {got_response, Addr}} -> + ?ERR("ma_v2_inform1 -> " + "received unexpected snmp_notification " + "[with manager response] from: ~n ~p", [Addr]), + {error, got_response}; + {snmp_notification, Tag07, {no_response, Addr}} -> + ?DBG("ma_v2_inform1 -> " + "received expected snmp_notification " + "[without manager response] from: ~n ~p", + [Addr]), + ok + after + 240000 -> + ?ERR("ma_v2_inform1 -> " + "timeout awaiting snmp_notification [~p]", + [Tag07]), + {error, snmp_notification_timeout} + end + end, + + Commands = + [ + { 1, "Send notification [no receiver]", Cmd01}, + { 2, "Expect inform [send response]", Cmd02}, + { 3, "Send notification [tag1]", Cmd03}, + { 4, "Expect inform [send response]", Cmd04}, + { 5, "Expect snmp_targets message [from trap sender]", Cmd05}, + { 6, "Expect snmp_notification [got_response] message [from trap sender]", Cmd06}, + { 7, "Send notification [tag2]", Cmd07}, + { 8, "Expect inform [don't send response]", Cmd08}, + { 9, "Expect snmp_targets message [from trap sender]", Cmd09}, + {10, "Expect snmp_notification [no_response] message [from trap sender]", Cmd10} + ], + + command_handler(Commands). + + +%% Note: This test case takes a while... actually a couple of minutes. +ma_v2_inform2(MA) -> + ?DBG("ma_v2_inform2 -> entry with" + "~n MA = ~p => " + "~n send notification: testTrapv22", [MA]), + + CmdExpectInform = + fun(No, Response) -> + expect(No, + {inform, Response}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]) + end, + + CmdExp = + fun(ok) -> + ok; + ({ok, Val}) -> + ?DBG("ma_v2_inform -> [cmd2] Val: ~p", [Val]), + ok; + ({error, Id, Extra}) -> + {error, {unexpected, Id, Extra}}; + (Error) -> + Error + end, + + %% Await callback(s) + CmdAwaitDeliveryCallback = + fun(Kind, Ref, Tag) -> + io:format("CmdAwaitDeliveryCallback -> entry with" + "~n Kind: ~p" + "~n Ref: ~p" + "~n Tag: ~p" + "~n", [Kind, Ref, Tag]), + receive + {Kind, Ref, ok} -> + io:format("CmdAwaitDeliveryCallback(~p,~p) -> received expected result: ok" + "~n", [Tag, Ref]), + ok; + {Kind, Ref, Error} -> + io:format("CmdAwaitDeliveryCallback(~p,~p) -> received unexpected result: " + "~n Error: ~p" + "~n", [Tag, Ref, Error]), + {error, {unexpected_response, Error}} + after + 240000 -> + ?ERR("ma_v2_inform2 -> " + "timeout awaiting got_response for snmp_notification [~p]", + [Tag]), + {error, snmp_notification_timeout} + end + end, + + Tag11 = tag21, + Ref11 = make_ref(), + Extra11 = [{tag, Tag11}, + {ref, Ref11}, + {recv, self()}, + {targets, []}, + {address, dummy}, + {expected_delivery_result, got_response}], + Recv11 = #snmpa_notification_delivery_info{tag = Tag11, + mod = ?MODULE, + extra = Extra11}, + Cmd11 = + fun() -> + snmpa:send_notification(MA, testTrapv22, + Recv11, + "standard inform", []), + ok + end, + Cmd12 = + fun() -> + Res = CmdExpectInform(4, true), + CmdExp(Res) + end, + + Cmd13 = fun() -> CmdAwaitDeliveryCallback(targets, Ref11, Tag11) end, + Cmd14 = fun() -> CmdAwaitDeliveryCallback(info, Ref11, Tag11) end, + + Commands = + [ + {11, "Send notification [tag3]", Cmd11}, + {12, "Expect notification message [tag3]", Cmd12}, + {13, "Expect targets message [tag3]", Cmd13}, + {14, "Expect notification response message [tag3]", Cmd14} + ], + + command_handler(Commands). + + +%% Note: This test case takes a while... actually a couple of minutes. +ma_v2_inform3(MA) -> + ?DBG("ma_v2_inform3 -> entry with" + "~n MA = ~p => " + "~n send notification: testTrapv22", [MA]), + + CmdExpectInform = + fun(No, Response) -> + expect(No, + {inform, Response}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]) + end, + + CmdExp = + fun(ok) -> + ok; + ({ok, Val}) -> + ?DBG("ma_v2_inform3 -> [cmd2] Val: ~p", [Val]), + ok; + ({error, Id, Extra}) -> + {error, {unexpected, Id, Extra}}; + (Error) -> + Error + end, + + %% Await callback(s) + CmdAwaitDeliveryCallback = + fun(Kind, Ref, Tag) -> + io:format("CmdAwaitDeliveryCallback -> entry with" + "~n Kind: ~p" + "~n Ref: ~p" + "~n Tag: ~p" + "~n", [Kind, Ref, Tag]), + receive + {Kind, Ref, ok} -> + io:format("CmdAwaitDeliveryCallback(~p,~p) -> received expected result: ok" + "~n", [Tag, Ref]), + ok; + {Kind, Ref, Error} -> + io:format("CmdAwaitDeliveryCallback(~p,~p) -> received unexpected result: " + "~n Error: ~p" + "~n", [Tag, Ref, Error]), + {error, {unexpected_response, Error}} + after + 240000 -> + ?ERR("ma_v2_inform3 -> " + "timeout awaiting got_response for snmp_notification [~p]", + [Tag]), + {error, snmp_notification_timeout} + end + end, + + Tag15 = tag31, + Ref15 = make_ref(), + Extra15 = [{tag, Tag15}, + {ref, Ref15}, + {recv, self()}, + {targets, []}, + {address, dummy}, + {expected_delivery_result, no_response}], + Recv15 = #snmpa_notification_delivery_info{tag = Tag15, + mod = ?MODULE, + extra = Extra15}, + Cmd15 = + fun() -> + snmpa:send_notification(MA, testTrapv22, + Recv15, + "standard inform", []), + ok + end, + Cmd16 = + fun() -> + Res = CmdExpectInform(5, false), + CmdExp(Res) + end, + + Cmd17 = fun() -> CmdAwaitDeliveryCallback(targets, Ref15, Tag15) end, + Cmd18 = fun() -> CmdAwaitDeliveryCallback(info, Ref15, Tag15) end, + + Commands = + [ + {15, "Send notification [tag31]", Cmd15}, + {16, "Expect notification message [tag31]", Cmd16}, + {17, "Expect targets message [tag31]", Cmd17}, + {18, "Expect notification (no) response message [tag31]", Cmd18} + ], + + command_handler(Commands). + + +delivery_targets(Tag, Addresses, Extra) -> + io:format("~w:delivery_targets -> entry with" + "~n Tag: ~p" + "~n Addresses: ~p" + "~n Extra: ~p" + "~n", [?MODULE, Tag, Addresses, Extra]), + {value, {_, Pid}} = lists:keysearch(recv, 1, Extra), + {value, {_, Ref}} = lists:keysearch(ref, 1, Extra), + case lists:keysearch(tag, 1, Extra) of + {value, {_, Tag}} -> + Pid ! {targets, Ref, ok}; + {value, {_, OtherTag}} -> + Pid ! {targets, Ref, {error, {wrong_tag, Tag, OtherTag}}} + end, + ok. + +delivery_info(Tag, Address, DeliveryResult, Extra) -> + io:format("~w:delivery_info -> entry with" + "~n Tag: ~p" + "~n Address: ~p" + "~n DeliveryResult: ~p" + "~n Extra: ~p" + "~n", [?MODULE, Tag, Address, DeliveryResult, Extra]), + {value, {_, Pid}} = lists:keysearch(recv, 1, Extra), + {value, {_, Ref}} = lists:keysearch(ref, 1, Extra), + case lists:keysearch(tag, 1, Extra) of + {value, {_, Tag}} -> + Pid ! {info, Ref, ok}; + {value, {_, OtherTag}} -> + Pid ! {info, Ref, {error, {wrong_tag, Tag, OtherTag}}} + end, + ok. + + +command_handler([]) -> + ok; +command_handler([{No, Desc, Cmd}|Rest]) -> + ?LOG("command_handler -> command ~w: ~n ~s", [No, Desc]), + case (catch Cmd()) of + ok -> + ?LOG("command_handler -> ~w: ok",[No]), + command_handler(Rest); + {error, Reason} -> + ?ERR("command_handler -> ~w error: ~n~p",[No, Reason]), + ?line ?FAIL(Reason); + Error -> + ?ERR("command_handler -> ~w unexpected: ~n~p",[No, Error]), + ?line ?FAIL({unexpected_command_result, Error}) + end. + + +ma_v1_2_v2_trap(MA) -> + snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmpTraps ++ [3]}, + {[ifIndex, 1], 1}, + {[snmpTrapEnterprise, 0], [1,2,3]}]). + + +ma_v1_2_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}, + {[snmpTrapEnterprise, 0], ?system}]). + + +sa_v1_2_v2_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + +sa_v1_2_v2_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], "pelle"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +sa_v1_2_v2_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 2]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_bad_value() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2}, + {[sa, [2,0]], 5}, % badValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, badValue, 2, any), + s([{NewKeyc3, 2}, + {[sa, [2,0]], 6}, % wrongValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, ?v1_2(badValue, wrongValue), 2, any), + g([NewKeyc4]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_gen_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2},{NewKeyc4, 2}, + {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]), + ?line expect(1, genErr, 4, any), +% The row might have been added; we don't know. +% (as a matter of fact we do - it is added, because the agent +% first sets its own vars, and then th SAs. Lets destroy it. + s([{NewKeyc5, ?destroy}]), + ?line expect(2, [{NewKeyc5, ?destroy}]). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_too_big() -> + g([[sa, [4,0]]]), + ?line expect(1, tooBig). + +%% Req. Klas1, system group, snmp group (v1/v2) +next_across_sa() -> + gn([[sysDescr],[klas1,5]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {[snmpInPkts, 0], any}]). + +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2} +%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2} +%% Req. Klas3, Klas4 +undo_test() -> + s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]), + ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any), + s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]), + ?line expect(3, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]), + ?line expect(4, ?v1_2(genErr, commitFailed), 1, any), +% unfortunatly we don't know if we'll get undoFailed or commitFailed. +% it depends on which order the agent traverses the varbind list. +% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]), +% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]), + ?line expect(6, genErr, 2, any). + +%% Req. Klas3, Klas4 +bad_return() -> + g([[fStatus4,4], + [fName4,4]]), + ?line expect(4, genErr, 2, any), + g([[fStatus4,5], + [fName4,5]]), + ?line expect(5, genErr, 1, any), + g([[fStatus4,6], + [fName4,6]]), + ?line expect(6, genErr, 2, any), + gn([[fStatus4,7], + [fName4,7]]), + ?line expect(7, genErr, 2, any), + gn([[fStatus4,8], + [fName4,8]]), + ?line expect(8, genErr, 1, any), + gn([[fStatus4,9], + [fName4,9]]), + ?line expect(9, genErr, 2, any). + + +%%%----------------------------------------------------------------- +%%% Test the implementation of standard mibs. +%%% We should *at least* try to GET all variables, just to make +%%% sure the instrumentation functions work. +%%% Note that many of the functions in the standard mib is +%%% already tested by the normal tests. +%%%----------------------------------------------------------------- +standard_mibs(suite) -> + [ + snmp_standard_mib, + snmp_community_mib, + snmp_framework_mib, + snmp_target_mib, + snmp_notification_mib, + snmp_view_based_acm_mib + ]. + +standard_mibs_2(suite) -> + [ + snmpv2_mib_2, + snmp_community_mib_2, + snmp_framework_mib_2, + snmp_target_mib_2, + snmp_notification_mib_2, + snmp_view_based_acm_mib_2 + ]. + +standard_mibs_3(suite) -> + [ + snmpv2_mib_3, + snmp_framework_mib_3, + snmp_mpd_mib_3, + snmp_target_mib_3, + snmp_notification_mib_3, + snmp_view_based_acm_mib_3, + snmp_user_based_sm_mib_3 + ]. + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v1. +%% o Test the counters and control objects in SNMP-STANDARD-MIB +%%----------------------------------------------------------------- +snmp_standard_mib(suite) -> []; +snmp_standard_mib(Config) when is_list(Config) -> + ?P(snmp_standard_mib), + init_case(Config), + ?DBG("snmp_standard_mib -> std_mib_init", []), + try_test(std_mib_init), + + ?DBG("snmp_standard_mib -> std_mib_a", []), + InBadVsns = try_test(std_mib_a), + put(vsn, v2), + ?DBG("snmp_standard_mib -> std_mib_read", []), + try_test(std_mib_read), + put(vsn, v1), + + ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]), + Bad = try_test(std_mib_b, [InBadVsns]), + ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []), + try_test(std_mib_read, [], [{community, "bad community"}]), + ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []), + try_test(std_mib_write, [], [{community, "public"}]), + ?DBG("snmp_standard_mib -> std_mib_asn_err", []), + try_test(std_mib_asn_err), + ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]), + try_test(std_mib_c, [Bad]), + ?DBG("snmp_standard_mib -> std_mib_a", []), + try_test(standard_mib_a), + + ?DBG("snmp_standard_mib -> std_mib_finish", []), + try_test(std_mib_finish), + ?DBG("snmp_standard_mib -> std_mib_test_finish", []), + try_test(standard_mib_test_finish, [], [{community, "bad community"}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_a() -> + ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]), + ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]), + ?line OutPkts2 = OutPkts + 1, + %% There are some more counters we could test here, but it's not that + %% important, since they are removed from SNMPv2-MIB. + ok. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_init() -> + %% disable authentication failure traps. (otherwise w'd get many of + %% them - this is also a test to see that it works). + s([{[snmpEnableAuthenTraps,0], 2}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_finish() -> + %% enable again + s([{[snmpEnableAuthenTraps,0], 1}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_test_finish() -> + %% force a authenticationFailure + std_mib_write(), + %% check that we got a trap + ?line expect(2, trap, [1,2,3], 4, 0, []). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_read() -> + ?DBG("std_mib_read -> entry", []), + g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply + ?DBG("std_mib_read -> await timeout (i.e. no reply)", []), + ?line expect(1, timeout). % make sure we don't get a trap! + + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_write() -> + ?DBG("std_mib_write -> entry", []), + s([{[sysLocation, 0], "new_value"}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_asn_err() -> + snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]). + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v2 and v3. +%% o Test the counters and control objects in SNMPv2-MIB +%%----------------------------------------------------------------- +snmpv2_mib_2(suite) -> []; +snmpv2_mib_2(Config) when is_list(Config) -> + ?P(snmpv2_mib_2), + ?LOG("snmpv2_mib_2 -> start",[]), + init_case(Config), + + ?DBG("snmpv2_mib_2 -> standard mib init",[]), + try_test(std_mib_init), + + ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]), + InBadVsns = try_test(std_mib_a), + + ?DBG("snmpv2_mib_2 -> make a bad version read",[]), + put(vsn, v1), + try_test(std_mib_read), + + ?DBG("snmpv2_mib_2 -> bad version read",[]), + put(vsn, v2), + Bad = try_test(std_mib_b, [InBadVsns]), + + ?DBG("snmpv2_mib_2 -> read with bad community",[]), + try_test(std_mib_read, [], [{community, "bad community"}]), + + ?DBG("snmpv2_mib_2 -> write with public community",[]), + try_test(std_mib_write, [], [{community, "public"}]), + + ?DBG("snmpv2_mib_2 -> asn err",[]), + try_test(std_mib_asn_err), + + ?DBG("snmpv2_mib_2 -> check counters",[]), + try_test(std_mib_c, [Bad]), + + ?DBG("snmpv2_mib_2 -> get som counters",[]), + try_test(snmpv2_mib_a), + + ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]), + try_test(std_mib_finish), + + ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, " + "then disable auth traps",[]), + try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]), + + ?LOG("snmpv2_mib_2 -> done",[]). + +%% Req. SNMPv2-MIB +snmpv2_mib_3(suite) -> []; +snmpv2_mib_3(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + ?P(snmpv2_mib_3), + init_case(Config), + + InBadVsns = try_test(std_mib_a), + put(vsn, v1), + try_test(std_mib_read), + put(vsn, v3), + _Bad = try_test(std_mib_b, [InBadVsns]), + try_test(snmpv2_mib_a), + + try_test(std_mib_finish). + +-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]). + +%% Req. SNMPv2-MIB +snmpv2_mib_test_finish() -> + %% force a authenticationFailure + ?DBG("ma_v2_inform -> write to std mib",[]), + std_mib_write(), + + %% check that we got a trap + ?DBG("ma_v2_inform -> await trap",[]), + ?line expect(2, v2trap, [{[sysUpTime,0], any}, + {[snmpTrapOID,0], ?authenticationFailure}]), + + %% and the the inform + ?DBG("ma_v2_inform -> await inform",[]), + ?line expect(2, {inform,true}, [{[sysUpTime,0], any}, + {[snmpTrapOID,0],?authenticationFailure}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_a() -> + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + + ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]), + InBadVsns. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_b(InBadVsns) -> + ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]), + ?line InBadVsns2 = InBadVsns + 1, + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] = + get_req(4, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + {InBadCommunityNames, InBadCommunityUses, InASNErrs}. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) -> + ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] = + get_req(1, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + ?line InBadCommunityNames2 = InBadCommunityNames + 1, + ?line InBadCommunityUses2 = InBadCommunityUses + 1, + ?line InASNErrs2 = InASNErrs + 1. + +%% Req. SNMPv2-MIB +snmpv2_mib_a() -> + ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]), + s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]), + ?line expect(3, [{[snmpSetSerialNo,0], SetSerial}, + {[sysLocation, 0], "val2"}]), + s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]), + ?line expect(4, inconsistentValue, 2, + [{[sysLocation, 0], "val3"}, + {[snmpSetSerialNo,0], SetSerial}]), + ?line ["val2"] = get_req(5, [[sysLocation,0]]). + + +%%----------------------------------------------------------------- +%% o Bad community uses/name is tested already +%% in SNMPv2-MIB and STANDARD-MIB. +%% o Test add/deletion of rows. +%%----------------------------------------------------------------- +snmp_community_mib(suite) -> []; +snmp_community_mib(Config) when is_list(Config) -> + ?P(snmp_community_mib), + init_case(Config), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + try_test(snmp_community_mib), + ?line unload_master("SNMP-COMMUNITY-MIB"). + +snmp_community_mib_2(X) -> ?P(snmp_community_mib_2), snmp_community_mib(X). + +%% Req. SNMP-COMMUNITY-MIB +snmp_community_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o Test engine boots / time +%%----------------------------------------------------------------- +snmp_framework_mib(suite) -> []; +snmp_framework_mib(Config) when is_list(Config) -> + ?P(snmp_framework_mib), + init_case(Config), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + try_test(snmp_framework_mib), + ?line unload_master("SNMP-FRAMEWORK-MIB"). + +snmp_framework_mib_2(X) -> ?P(snmp_framework_mib_2), snmp_framework_mib(X). + +snmp_framework_mib_3(suite) -> []; +snmp_framework_mib_3(Config) when is_list(Config) -> + ?P(snmp_framework_mib_3), + init_case(Config), + try_test(snmp_framework_mib). + + +%% Req. SNMP-FRAMEWORK-MIB +snmp_framework_mib() -> + ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]), + ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]), + ?SLEEP(5000), + ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]), + ?DBG("snmp_framework_mib -> time(s): " + "~n EngineTime 1 = ~p" + "~n EngineTime 2 = ~p", [EngineTime, EngineTime2]), + if + (EngineTime+7) < EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + (EngineTime+4) > EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + true -> + ok + end, + ?line case get_req(4, [[snmpEngineBoots,0]]) of + [Boots] when is_integer(Boots) -> + ok; + Else -> + ?FAIL(Else) + end, + ok. + +%%----------------------------------------------------------------- +%% o Test the counters +%%----------------------------------------------------------------- +snmp_mpd_mib_3(suite) -> []; +snmp_mpd_mib_3(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + ?P(snmp_mpd_mib_3), + init_case(Config), + UnknownPDUHs = try_test(snmp_mpd_mib_a), + try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]), + try_test(snmp_mpd_mib_c, [UnknownPDUHs]). + + +%% Req. SNMP-MPD-MIB +snmp_mpd_mib_a() -> + ?line [UnknownSecs, InvalidMsgs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0]]), + Pdu = #pdu{type = 'get-request', + request_id = 23, + error_status = noError, + error_index = 0, + varbinds = []}, + SPdu = #scopedPdu{contextEngineID = "agentEngine", + contextName = "", + data = Pdu}, + ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu), + V3Hdr1 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [7], + msgSecurityModel = 23, % bad sec model + msgSecurityParameters = []}, + V3Hdr2 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [6], % bad flag combination + msgSecurityModel = 3, + msgSecurityParameters = []}, + Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1, + data = SPDUBytes}, + Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2, + data = SPDUBytes}, + ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1), + ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2), + snmp_test_mgr:send_bytes(MsgBytes1), + snmp_test_mgr:send_bytes(MsgBytes2), + + ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0], + [snmpUnknownPDUHandlers, 0]]), + ?line UnknownSecs2 = UnknownSecs + 1, + ?line InvalidMsgs2 = InvalidMsgs + 1, + UnknownPDUHs. + +-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]). +snmp_mpd_mib_b() -> + g([[sysUpTime,0]]), + ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]). + + +snmp_mpd_mib_c(UnknownPDUHs) -> + ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]), + ?line UnknownPDUHs2 = UnknownPDUHs + 1. + + +snmp_target_mib(suite) -> []; +snmp_target_mib(Config) when is_list(Config) -> + ?P(snmp_target_mib), + init_case(Config), + ?line load_master_std("SNMP-TARGET-MIB"), + try_test(snmp_target_mib), + ?line unload_master("SNMP-TARGET-MIB"). + +snmp_target_mib_2(X) -> ?P(snmp_target_mib_2), snmp_target_mib(X). + +snmp_target_mib_3(X) -> ?P(snmp_target_mib_3), snmp_target_mib(X). + +snmp_target_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +snmp_notification_mib(suite) -> []; +snmp_notification_mib(Config) when is_list(Config) -> + ?P(snmp_notification_mib), + init_case(Config), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + try_test(snmp_notification_mib), + ?line unload_master("SNMP-NOTIFICATION-MIB"). + +snmp_notification_mib_2(X) -> ?P(snmp_notification_mib_2), + snmp_notification_mib(X). + +snmp_notification_mib_3(X) -> ?P(snmp_notification_mib_3), + snmp_notification_mib(X). + +snmp_notification_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o add/delete views and try them +%% o try boundaries +%%----------------------------------------------------------------- +snmp_view_based_acm_mib(suite) -> []; +snmp_view_based_acm_mib(Config) when is_list(Config) -> + ?P(snmp_view_based_acm_mib), + init_case(Config), + + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master("Test2"), + snmp_view_based_acm_mib(), + ?line unload_master("Test2"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +snmp_view_based_acm_mib_2(X) -> + ?P(snmp_view_based_acm_mib_2), + snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib_3(X) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(X, Condition), + %% </CONDITIONAL-SKIP> + + ?P(snmp_view_based_acm_mib_3), + snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib() -> + snmpa:verbosity(net_if,trace), + snmpa:verbosity(master_agent,trace), + ?LOG("start snmp_view_based_acm_mib test",[]), + %% The user "no-rights" is present in USM, and is mapped to security + %% name 'no-rights", which is not present in VACM. + %% So, we'll add rights for it, try them and delete them. + %% We'll give "no-rights" write access to tDescr.0 and read access + %% to tDescr2.0 + %% These are the options we'll use to the mgr + Opts = [{user, "no-rights"}, {community, "no-rights"}], + %% Find the valid secmodel, and one invalid secmodel. + {SecMod, InvSecMod} = + case get(vsn) of + v1 -> {?SEC_V1, ?SEC_V2C}; + v2 -> {?SEC_V2C, ?SEC_USM}; + v3 -> {?SEC_USM, ?SEC_V1} + end, + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Now, add a mapping from "no-rights" -> "no-rights-group" + GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]], + GRow1 = + [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"}, + {GRow1Status, ?createAndGo}], + ?DBG("set '~p'",[GRow1]), + ?line try_test(do_set, [GRow1]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Create a mapping for another sec model, and make sure it dosn't + %% give us access + GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]], + GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"}, + {GRow2Status, ?createAndGo}], + + ?DBG("set '~p'",[GRow2]), + ?line try_test(do_set, [GRow2]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [GRow2Status]), + + RVName = "rv_name", + WVName = "wv_name", + + %% Access row + ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1], + ARow1Status = [vacmAccessStatus, ARow1Idx], + ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1}, + {[vacmAccessReadViewName, ARow1Idx], RVName}, + {[vacmAccessWriteViewName, ARow1Idx], WVName}, + {ARow1Status, ?createAndGo}], + + %% This access row would give acces, if InvSecMod was valid. + ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1], + ARow2Status = [vacmAccessStatus, ARow2Idx], + ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1}, + {[vacmAccessReadViewName, ARow2Idx], "internet"}, + {[vacmAccessWriteViewName, ARow2Idx], "internet"}, + {ARow2Status, ?createAndGo}], + + ?line try_test(do_set, [ARow2]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [ARow2Status]), + + + %% Add valid row + ?line try_test(do_set, [ARow1]), + + ?line try_test(use_no_rights, [], Opts), + + %% Create the view family + VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access + VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access + VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access + VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access + VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx], + VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx], + VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx], + VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx], + + ?line try_test(add_row, [VRow1Status]), + ?line try_test(add_row, [VRow2Status]), + ?line try_test(add_row, [VRow3Status]), + + %% We're supposed to have access now... + ?line try_test(use_rights, [], Opts), + + %% Change Row3 to Row4 + ?line try_test(del_row, [VRow3Status]), + ?line try_test(add_row, [VRow4Status]), + + %% We should still have access... + ?line try_test(use_rights, [], Opts), + + %% Delete rows + ?line try_test(del_row, [GRow1Status]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete rest of rows + ?line try_test(del_row, [ARow1Status]), + ?line try_test(del_row, [VRow1Status]), + ?line try_test(del_row, [VRow2Status]), + ?line try_test(del_row, [VRow4Status]), + + ?line try_test(use_no_rights, [], Opts), + snmpa:verbosity(master_agent,log). + +do_set(Row) -> + s(Row), + expect(1, Row). + +add_row(RowStatus) -> + s([{RowStatus, ?createAndGo}]), + expect(1, [{RowStatus, ?createAndGo}]). + +del_row(RowStatus) -> + s([{RowStatus, ?destroy}]), + expect(1, [{RowStatus, ?destroy}]). + + + +use_no_rights() -> + g([[xDescr,0]]), + ?v1_2_3(expect(11, noSuchName, 1, any), + expect(12, [{[xDescr,0], noSuchObject}]), + expect(13, authorizationError, 1, any)), + g([[xDescr2,0]]), + ?v1_2_3(expect(21, noSuchName, 1, any), + expect(22, [{[xDescr2,0], noSuchObject}]), + expect(23, authorizationError, 1, any)), + gn([[xDescr]]), + ?v1_2_3(expect(31, noSuchName, 1, any), + expect(32, [{[xDescr], endOfMibView}]), + expect(33, authorizationError, 1, any)), + s([{[xDescr,0], "tryit"}]), + ?v1_2_3(expect(41, noSuchName, 1, any), + expect(42, noAccess, 1, any), + expect(43, authorizationError, 1, any)). + + +use_rights() -> + g([[xDescr,0]]), + expect(1, [{[xDescr,0], any}]), + g([[xDescr2,0]]), + expect(2, [{[xDescr2,0], any}]), + s([{[xDescr,0], "tryit"}]), + expect(3, noError, 0, any), + g([[xDescr,0]]), + expect(4, [{[xDescr,0], "tryit"}]). + +mk_ln(X) -> + [length(X) | X]. + +%%----------------------------------------------------------------- +%% o add/delete users and try them +%% o test all secLevels +%% o test all combinations of protocols +%% o try bad ops; check counters +%%----------------------------------------------------------------- +snmp_user_based_sm_mib_3(suite) -> []; +snmp_user_based_sm_mib_3(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + ?P(snmp_user_based_sm_mib_3), + init_case(Config), + + _AgentDir = ?config(agent_dir, Config), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + + %% The newUser used here already has VACM access. + + %% Add a new user in the simplest way; just createAndGo + try_test(v3_sync, [[{usm_add_user1, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new user + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"), + DesKey1 = lists:sublist(ShaKey1, 16), + + %% Change the new user's keys - 1 + try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + MgrDir = ?config(mgr_dir, Config), + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"), + DesKey2 = lists:sublist(ShaKey2, 16), + + %% Change the new user's keys - 2 + ?line try_test(v3_sync, + [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + reset_usm_mgr(MgrDir), + ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2), + ?line load_master("Test2"), + ?line try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Change the new user's keys - 3 + ?line try_test(v3_sync, + [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new keys + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Try some read requests + ?line try_test(v3_sync, [[{usm_read, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Delete the new user + ?line try_test(v3_sync, [[{usm_del_user, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try some bad requests + ?line try_test(v3_sync, [[{usm_bad, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("SNMP-USER-BASED-SM-MIB"). + +-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]). + +usm_add_user1() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +usm_use_user() -> + v2_proc(). + + +%% Change own public keys +usm_key_change1(ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_shaxxxxxxxxxx", + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_desxxxxxx", + DesKey), + Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change own private keys +usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change other's public keys +usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}], + s(Vbs1), + ?line expect(1, noAccess, 1, any), + Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs2), + ?line expect(2, noAccess, 1, any), + + + Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs3), + ?line expect(1, Vbs3). + +usm_read() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ?line g([[usmUserSecurityName, NewRowIndex], + [usmUserCloneFrom, NewRowIndex], + [usmUserAuthKeyChange, NewRowIndex], + [usmUserOwnAuthKeyChange, NewRowIndex], + [usmUserPrivKeyChange, NewRowIndex], + [usmUserOwnPrivKeyChange, NewRowIndex]]), + ?line expect(1, + [{[usmUserSecurityName, NewRowIndex], "newUser"}, + {[usmUserCloneFrom, NewRowIndex], [0,0]}, + {[usmUserAuthKeyChange, NewRowIndex], ""}, + {[usmUserOwnAuthKeyChange, NewRowIndex], ""}, + {[usmUserPrivKeyChange, NewRowIndex], ""}, + {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]), + ok. + + + +usm_del_user() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]). + +-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]). + +-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]). + +-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]). + +-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]). + +-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]). + +usm_bad() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, inconsistentName, 1, any), + + RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs2), + ?line expect(2, wrongValue, 1, any), + + RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs3), + ?line expect(3, Vbs3), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]), + ?line expect(4, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]), + ?line expect(5, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]), + ?line expect(6, wrongValue, 1, any), + ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]), + ?line expect(7, wrongValue, 1, any), + + Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs4), + ?line expect(1, Vbs4), + + ok. + + +%%----------------------------------------------------------------- +%% Loop through entire MIB, to make sure that all instrum. funcs +%% works. +%% Load all std mibs that are not loaded by default. +%%----------------------------------------------------------------- +loop_mib(suite) -> []; +loop_mib(Config) when is_list(Config) -> + ?P(loop_mib), + ?LOG("loop_mib -> initiate case",[]), + %% snmpa:verbosity(master_agent,debug), + %% snmpa:verbosity(mib_server,info), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]), + ?line load_master_std("SNMP-MPD-MIB"), + ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?DBG("loop_mib -> try",[]), + try_test(loop_mib_1), + ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]), + ?line unload_master("SNMP-MPD-MIB"), + ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + %% snmpa:verbosity(master_agent,log), + %% snmpa:verbosity(mib_server,silence), + ?LOG("loop_mib -> done",[]). + + +loop_mib_2(suite) -> []; +loop_mib_2(Config) when is_list(Config) -> + ?P(loop_mib_2), + ?LOG("loop_mib_2 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_2 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_2 -> load mibs",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_2 -> unload mibs",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?LOG("loop_mib_2 -> done",[]). + + +loop_mib_3(suite) -> []; +loop_mib_3(Config) when is_list(Config) -> + ?P(loop_mib_3), + ?LOG("loop_mib_3 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_3 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_3 -> load mibs",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + + try_test(loop_mib_2), + + ?DBG("loop_mib_3 -> unload mibs",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?LOG("loop_mib_3 -> done",[]). + + +%% Req. As many mibs all possible +loop_mib_1() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_1([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_1(Oid, N) -> + ?DBG("loop_it_1 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type = 'get-response', + error_status = noError, + error_index = 0, + varbinds = [#varbind{oid = NOid, + value = Value}]} when NOid > Oid -> + ?DBG("loop_it_1 -> " + "~n NOid: ~p" + "~n Value: ~p",[NOid, Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_1 -> " + "~n Value2: ~p",[Value2]), + loop_it_1(NOid, N+1); + + #pdu{type = 'get-response', + error_status = noError, + error_index = 0, + varbinds = Vbs} -> + exit({unexpected_vbs, ?LINE, Vbs}); + + #pdu{type = 'get-response', + error_status = noSuchName, + error_index = 1, + varbinds = [_]} -> + ?DBG("loop_it_1 -> done: ~p",[N]), + N; + + #pdu{type = 'get-response', + error_status = Err, + error_index = Idx, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, Err, Idx, Vbs}); + + #pdu{type = Type, + error_status = Err, + error_index = Idx, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs}); + + {error, Reason} -> + exit({error, Reason, ?LINE}) + end. + + +%% Req. As many mibs all possible +loop_mib_2() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_2([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_2(Oid, N) -> + ?DBG("loop_it_2 -> entry with" + "~n Oid: ~p" + "~n N: ~p",[Oid, N]), + case get_next_req([Oid]) of + #pdu{type = 'get-response', + error_status = noError, + error_index = 0, + varbinds = [#varbind{oid = NOid, value = endOfMibView}]} -> + ?DBG("loop_it_2 -> " + "~n NOid: ~p",[NOid]), + N; + + #pdu{type = 'get-response', + error_status = noError, + error_index = 0, + varbinds = [#varbind{oid = NOid, + value = Value}]} when NOid > Oid -> + ?DBG("loop_it_2 -> " + "~n NOid: ~p" + "~n Value: ~p",[NOid, Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_2 -> " + "~n Value2: ~p",[Value2]), + loop_it_2(NOid, N+1); + + #pdu{type = 'get-response', + error_status = noError, + error_index = 0, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, + [{varbinds, Vbs}, + {get_next_oid, Oid}, + {counter, N}]}); + + #pdu{type = 'get-response', + error_status = ES, + error_index = EI, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, + [{error_status, ES}, + {error_index, EI}, + {varbinds, Vbs}, + {get_next_oid, Oid}, + {counter, N}]}); + + #pdu{type = Type, + error_status = ES, + error_index = EI, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, + [{type, Type}, + {error_status, ES}, + {error_index, EI}, + {varbinds, Vbs}, + {get_next_oid, Oid}, + {counter, N}]}); + + {error, Reason} -> + exit({unexpected_result, ?LINE, + [{reason, Reason}, + {get_next_oid, Oid}, + {counter, N}]}) + + end. + + +%%%----------------------------------------------------------------- +%%% Testing of reported bugs and other tickets. +%%%----------------------------------------------------------------- + +reported_bugs(suite) -> + [ + otp_1128, + otp_1129, + otp_1131, + otp_1162, + otp_1222, + otp_1298, + otp_1331, + otp_1338, + otp_1342, + otp_2776, + otp_2979, + otp_3187, + otp_3725 + ]. + +reported_bugs_2(suite) -> + [ + otp_1128_2, + otp_1129_2, + otp_1131_2, + otp_1162_2, + otp_1222_2, + otp_1298_2, + otp_1331_2, + otp_1338_2, + otp_1342_2, + otp_2776_2, + otp_2979_2, + otp_3187_2 + ]. + +reported_bugs_3(suite) -> + [ + otp_1128_3, + otp_1129_3, + otp_1131_3, + otp_1162_3, + otp_1222_3, + otp_1298_3, + otp_1331_3, + otp_1338_3, + otp_1342_3, + otp_2776_3, + otp_2979_3, + otp_3187_3, + otp_3542 + ]. + + +%% These are (ticket) test cases where the initiation has to be done +%% individually. +tickets(suite) -> + [ + otp_4394, + otp_7157 + ]. + +%%----------------------------------------------------------------- +%% Ticket: OTP-1128 +%% Slogan: Bug in handling of createAndWait set-requests. +%%----------------------------------------------------------------- +otp_1128(suite) -> []; +otp_1128(Config) when is_list(Config) -> + ?P(otp_1128), + init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1128), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1128_2(X) -> ?P(otp_1128_2), otp_1128(X). + +otp_1128_3(X) -> ?P(otp_1128_3), otp_1128(X). + +otp_1128() -> + io:format("Testing bug reported in ticket OTP-1128...~n"), + + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + + s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(29, [{NewKeyc5, ?notReady}]), + s([{NewKeyc5, ?active}, {NewKeyc3, 2}]), + ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(31, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(32, [{NewKeyc5, ?destroy}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1129, OTP-1169 +%% Slogan: snmpa:int_to_enum crashes on bad oids +%%----------------------------------------------------------------- +otp_1129(suite) -> []; +otp_1129(Config) when is_list(Config) -> + ?P(otp_1129), + init_case(Config), + ?line load_master("Klas3"), + try_test(otp_1129_i, [node()]), + ?line unload_master("Klas3"). + +otp_1129_2(X) -> ?P(otp_1129_2), otp_1129(X). + +otp_1129_3(X) -> ?P(otp_1129_3), otp_1129(X). + +otp_1129_i(MaNode) -> + io:format("Testing bug reported in ticket OTP-1129...~n"), + false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]), + false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1131 +%% Slogan: Agent crashes / erlang node halts if RowIndex in a +%% setrequest is of bad type, e.g. an INDEX {INTEGER}, +%% and RowIdenx [3,2]. +%%----------------------------------------------------------------- +otp_1131(suite) -> []; +otp_1131(Config) when is_list(Config) -> + ?P(otp_1131), + init_case(Config), + + ?line load_master("Klas1"), + try_test(otp_1131), + ?line unload_master("Klas1"). + +otp_1131_2(X) -> ?P(otp_1131_2), otp_1131(X). + +otp_1131_3(X) -> + %% <CONDITIONAL-SKIP> + Skippable = [{unix, [darwin]}], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(X, Condition), + %% </CONDITIONAL-SKIP> + + ?P(otp_1131_3), + otp_1131(X). + +otp_1131() -> + io:format("Testing bug reported in ticket OTP-1131...~n"), + s([{[friendsEntry, [2, 3, 1]], s, "kompis3"}, + {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1162 +%% Slogan: snmp_agent can't handle wrongValue from instrum.func +%%----------------------------------------------------------------- +otp_1162(suite) -> []; +otp_1162(Config) when is_list(Config) -> + ?P(otp_1162), + {SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + try_test(otp_1162), + stop_subagent(SA). + +otp_1162_2(X) -> ?P(otp_1162_2), otp_1162(X). + +otp_1162_3(X) -> ?P(otp_1162_3), otp_1162(X). + +otp_1162() -> + s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok) + ?line expect(1, ?v1_2(badValue, wrongValue), 1, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1222 +%% Slogan: snmp agent crash if faulty index is returned from instrum +%%----------------------------------------------------------------- +otp_1222(suite) -> []; +otp_1222(Config) when is_list(Config) -> + ?P(otp_1222), + init_case(Config), + ?line load_master("Klas3"), + ?line load_master("Klas4"), + try_test(otp_1222), + ?line unload_master("Klas3"), + ?line unload_master("Klas4"). + +otp_1222_2(X) -> ?P(otp_1222_2), otp_1222(X). + +otp_1222_3(X) -> ?P(otp_1222_3), otp_1222(X). + +otp_1222() -> + io:format("Testing bug reported in ticket OTP-1222...~n"), + s([{[fStatus4,1], 4}, {[fName4,1], 1}]), + ?line expect(1, genErr, 0, any), + s([{[fStatus4,2], 4}, {[fName4,2], 1}]), + ?line expect(2, genErr, 0, any). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1298 +%% Slogan: Negative INTEGER values are treated as positive. +%%----------------------------------------------------------------- +otp_1298(suite) -> []; +otp_1298(Config) when is_list(Config) -> + ?P(otp_1298), + init_case(Config), + + ?line load_master("Klas2"), + try_test(otp_1298), + ?line unload_master("Klas2"). + +otp_1298_2(X) -> ?P(otp_1298_2), otp_1298(X). + +otp_1298_3(X) -> ?P(otp_1298_3), otp_1298(X). + +otp_1298() -> + io:format("Testing bug reported in ticket OTP-1298...~n"), + s([{[fint,0], -1}]), + ?line expect(1298, [{[fint,0], -1}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1331 +%% Slogan: snmp_generic should return noError when deleting non-ex row +%%----------------------------------------------------------------- +otp_1331(suite) -> []; +otp_1331(Config) when is_list(Config) -> + ?P(otp_1331), + init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1331), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1331_2(X) -> ?P(otp_1331_2), otp_1331(X). + +otp_1331_3(X) -> ?P(otp_1331_3), otp_1331(X). + +otp_1331() -> + NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")], + s([{NewKeyc5, ?destroy}]), + ?line expect(1, [{NewKeyc5, ?destroy}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1338 +%% Slogan: snmp bug in initialisation of default values for mnesia tabs +%%----------------------------------------------------------------- +otp_1338(suite) -> []; +otp_1338(Config) when is_list(Config) -> + ?P(otp_1338), + init_case(Config), + + ?line load_master("Klas2"), + try_test(otp_1338), + ?line unload_master("Klas2"). + +otp_1338_2(X) -> ?P(otp_1338_2), otp_1338(X). + +otp_1338_3(X) -> ?P(otp_1338_3), otp_1338(X). + +otp_1338() -> + s([{[kStatus2, 7], i, ?createAndGo}]), + ?line expect(1, [{[kStatus2, 7], ?createAndGo}]), + g([[kName2, 7]]), + ?line expect(2, [{[kName2, 7], "JJJ"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1342 +%% Slogan: default impl of snmp table can't handle bad index access, +%% Set when INDEX is read-write gets into an infinite loop! +%%----------------------------------------------------------------- +otp_1342(suite) -> []; +otp_1342(Config) when is_list(Config) -> + ?P(otp_1342), + init_case(Config), + ?line load_master("Klas4"), + try_test(otp_1342), + ?line unload_master("Klas4"). + +otp_1342_2(X) -> ?P(otp_1342_2), otp_1342(X). + +otp_1342_3(X) -> ?P(otp_1342_3), otp_1342(X). + +otp_1342() -> + s([{[fIndex5, 1], i, 1}, + {[fName5, 1], i, 3}, + {[fStatus5, 1], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1366 +%% Slogan: snmp traps not sent to all managers +%% Note: NYI! We need a way to tell the test server that we need +%% mgrs on two different machines. +%%----------------------------------------------------------------- +otp_1366(suite) -> []; +otp_1366(Config) when is_list(Config) -> + ?P(otp_1366), + init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1366), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1366_2(X) -> ?P(otp_1366_2), otp_1366(X). + +otp_1366_3(X) -> ?P(otp_1366_3), otp_1366(X). + +otp_1366() -> + ?INF("NOT YET IMPLEMENTED", []), + 'NYI'. + +%%----------------------------------------------------------------- +%% Ticket: OTP-2776 +%% Slogan: snmp:validate_date_and_time() fails when time is 00:00 +%%----------------------------------------------------------------- +otp_2776(suite) -> []; +otp_2776(Config) when is_list(Config) -> + ?P(otp_2776), + init_case(Config), + try_test(otp_2776). + +otp_2776_2(X) -> ?P(otp_2776_2), otp_2776(X). + +otp_2776_3(X) -> ?P(otp_2776_3), otp_2776(X). + +otp_2776() -> + io:format("Testing bug reported in ticket OTP-2776...~n"), + + Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0], + Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00 + Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0], + Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0], + Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0], + Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0], + Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2 + Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0], + Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4 + Dt10_invalid = [], + Dt11_invalid = [kalle,hobbe], + L = [{ 1, true, Dt01_valid}, + { 2, true, Dt02_valid}, + { 3, true, Dt03_valid}, + { 4, false, Dt04_invalid}, + { 5, true, Dt05_valid}, + { 6, true, Dt06_valid}, + { 7, false, Dt07_invalid}, + { 8, true, Dt08_valid}, + { 9, false, Dt09_invalid}, + {10, false, Dt10_invalid}, + {11, false, Dt11_invalid}], + + ?line ok = validate_dat(L). + + +validate_dat(L) -> validate_dat(L,[]). + +validate_dat([],V) -> + Fun = fun({_,X}) -> case X of + ok -> false; + _ -> true + end + end, + validate_dat1( lists:reverse( lists:filter(Fun,V) ) ); +validate_dat([{Id,E,Dat}|T],V) -> + validate_dat(T,[validate_dat2(Id,E,Dat) | V]). + +validate_dat1([]) -> ok; +validate_dat1(L) -> {error,L}. + +validate_dat2(Id, E, Dat) -> + Res = case {E,snmp:validate_date_and_time(Dat)} of + {E,E} -> ok; + {E,A} -> {E,A} + end, + {Id, Res}. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-2979 +%% Slogan: get-next on more than 1 column in an empty table +%% returns bad response. +%%----------------------------------------------------------------- +otp_2979(suite) -> []; +otp_2979(Config) when is_list(Config) -> + ?P(otp_2979), + init_case(Config), + ?line load_master("Test1"), + ?line init_old(), + try_test(otp_2979), + ?line unload_master("Test1"). + +otp_2979_2(X) -> ?P(otp_2979_2), otp_2979(X). + +otp_2979_3(X) -> ?P(otp_2979_3), otp_2979(X). + +otp_2979() -> + gn([[sparseDescr], [sparseStatus]]), + ?line expect(1, [{[sparseStr,0], "slut"}, + {[sparseStr,0], "slut"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3187 +%% Slogan: get-next on vacmAccessTable for colums > 5 returns +%% endOfTable - should return value. +%%----------------------------------------------------------------- +otp_3187(suite) -> []; +otp_3187(Config) when is_list(Config) -> + ?P(otp_3187), + init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + otp_3187(), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +otp_3187_2(X) -> ?P(otp_3187_2), otp_3187(X). + +otp_3187_3(X) -> ?P(otp_3187_3), otp_3187(X). + +otp_3187() -> + ?line Elements = + snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]), + lists:foreach(fun(E) -> + ?line if E == endOfTable -> + ?FAIL(endOfTable); + true -> ok + end + end, Elements). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3542 +%% Slogan: +%%----------------------------------------------------------------- +otp_3542(suite) -> []; +otp_3542(Config) when is_list(Config) -> + ?P(otp_3542), + init_case(Config), + try_test(otp_3542). + +otp_3542() -> + io:format("SNMP v3 discovery...~n"), + ?line Res = snmp_test_mgr:d(), + io:format("SNMP v3 discovery result: ~p~n",[Res]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-3725 +%% Slogan: Slow response time on snmpa:int_to_enum +%%----------------------------------------------------------------- +otp_3725(suite) -> []; +otp_3725(Config) when is_list(Config) -> + ?P(otp_3725), + init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_3725_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +%% Req. OLD-SNMPEA-MIB +otp_3725_test(MaNode) -> + io:format("Testing feature requested in ticket OTP-3725...~n"), + ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]), + ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]), + ?DBG("otp_3725_test -> Db = ~p",[Db]), + + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [Db, intAgentIpAddress]), + ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name, + [Db,OID]), + ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [Db, [1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [Db, intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum, + [Db, 'RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]), + ok. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-4394 +%% Slogan: Target mib tag list check invalid +%%----------------------------------------------------------------- + + +otp_4394(suite) -> {req, [], {conf, + init_otp_4394, + [otp_4394_test], + finish_otp_4394}}. + +init_otp_4394(Config) when is_list(Config) -> + ?DBG("init_otp_4394 -> entry with" + "~n Config: ~p", [Config]), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line otp_4394_config(AgentDir, MgrDir, Ip), + MasterAgentVerbosity = {master_agent_verbosity, trace}, + NetIfVerbosity = {net_if_verbosity, trace}, + Opts = [MasterAgentVerbosity,NetIfVerbosity], + [{vsn, v1} | start_v1_agent(Config,Opts)]. + +otp_4394_config(AgentDir, MgrDir, Ip0) -> + ?DBG("otp_4394_config -> entry with" + "~n AgentDir: ~p" + "~n MgrDir: ~p" + "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]), + Vsn = [v1], + Ip = tuple_to_list(Ip0), + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip, + ?TRAP_UDP, Ip, 4000, + "OTP-4394 test"), + ?line case update_usm(Vsn, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsn, MgrDir); + false -> + ?line ok + end, + C1 = {"a", "all-rights", "initial", "", "pc"}, + C2 = {"c", "secret", "secret_name", "", "secret_tag"}, + ?line write_community_conf(AgentDir, [C1, C2]), + ?line update_vacm(Vsn, AgentDir), + Ta1 = {"shelob v1", + [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda + "pc1", + "target_v1", "", + %% [255,255,255,255,0,0], + [], + 2048}, + Ta2 = {"bifur v1", + [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip + "pc2", + "target_v1", "", + %% [255,255,255,255,0,0], + [], 2048}, + ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]), + ?line write_target_params_conf(AgentDir, Vsn), + ?line write_notify_conf(AgentDir), + ok. + + + +finish_otp_4394(Config) when is_list(Config) -> + ?DBG("finish_otp_4394 -> entry", []), + C1 = stop_agent(Config), + delete_files(C1), + erase(mgr_node), + lists:keydelete(vsn, 1, C1). + +otp_4394_test(suite) -> []; +otp_4394_test(Config) -> + ?P(otp_4394_test), + ?DBG("otp_4394_test -> entry", []), + init_case(Config), + try_test(otp_4394_test1), + ?DBG("otp_4394_test -> done", []), + ok. + +otp_4394_test1() -> + ?DBG("otp_4394_test1 -> entry", []), + gn([[1,1]]), + Res = + case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of + %% {error, 1, {"?",[]}, {"~w",[timeout]}} + {error, 1, _, {_, [timeout]}} -> + ?DBG("otp_4394_test1 -> expected result: timeout", []), + ok; + Else -> + Else + end, + ?DBG("otp_4394_test1 -> done with: ~p", [Res]), + Res. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-7157 +%% Slogan: Target mib tag list check invalid +%%----------------------------------------------------------------- + + +otp_7157(suite) -> + {req, [], {conf, + init_otp_7157, + [otp_7157_test], + finish_otp_7157}}. + +init_otp_7157(Config) when is_list(Config) -> + %% <CONDITIONAL-SKIP> + Skippable = [win32], + Condition = fun() -> ?OS_BASED_SKIP(Skippable) end, + ?NON_PC_TC_MAYBE_SKIP(Config, Condition), + %% </CONDITIONAL-SKIP> + + ?DBG("init_otp_7157 -> entry with" + "~n Config: ~p", [Config]), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MasterAgentVerbosity = {master_agent_verbosity, trace}, + NetIfVerbosity = {net_if_verbosity, trace}, + Opts = [MasterAgentVerbosity, NetIfVerbosity], + [{vsn, v2} | start_v2_agent(Config, Opts)]. + + +finish_otp_7157(Config) when is_list(Config) -> + ?DBG("finish_otp_7157 -> entry", []), + C1 = stop_agent(Config), + delete_files(C1), + erase(mgr_node), + lists:keydelete(vsn, 1, C1). + +otp_7157_test(suite) -> []; +otp_7157_test(Config) -> + ?P(otp_7157_test), + ?DBG("otp_7157_test -> entry", []), + init_case(Config), + MA = whereis(snmp_master_agent), + ?line load_master("Test1"), + try_test(otp_7157_test1, [MA]), + ?line unload_master("Test1"), + ?DBG("otp_7157_test -> done", []), + ok. + +%% ts:run(snmp, snmp_agent_test, [batch]). +otp_7157_test1(MA) -> + ?LOG("start otp_7157_test1 test (~p)",[MA]), + snmpa:verbosity(MA, trace), + ?LOG("start otp_7157_test1 test",[]), + ?P1("Testing that varbinds in traps/notifications are not reordered"), + + ?DBG("send cntTrap",[]), + snmpa:send_trap(MA, cntTrap, "standard trap"), + + ?DBG("await response",[]), + %% We don't really care about the values, just the vb order. + ?line ok = expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], any}, + {[sysContact, 0], any}, + {[cnt64, 0], any}, + {[sysLocation, 0], any}]), + + ?DBG("done", []), + ok. + + + +%%----------------------------------------------------------------- +%% Slogan: info test +%%----------------------------------------------------------------- + +info_test(suite) -> []; +info_test(Config) when is_list(Config) -> + ?P(info_test), + init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(info_test1, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +info_test1(MaNode) -> + ?line Info = rpc:call(MaNode, snmpa, info, []), + ?DBG("info_test1 -> Info: ~n~p", [Info]), + Keys = [vsns, + stats_counters, + {agent, [process_memory, db_memory]}, + {net_if, [process_memory, port_info, reqs]}, + {note_store, [process_memory, db_memory]}, + {symbolic_store, [process_memory, db_memory]}, + {local_db, [process_memory, db_memory]}, + {mib_server, [process_memory, + loaded_mibs, + subagents, + tree_size_bytes, + db_memory]}], + verify_info(Info, Keys), + OldInfo = snmpa:old_info_format(Info), + ?DBG("info_test1 -> OldInfo: ~n~p", [OldInfo]), + verify_old_info(OldInfo), + ok. + +verify_info([], []) -> + ok; +verify_info([], Keys) -> + ?FAIL({remaining_info_keys, Keys}); +verify_info(Info0, [Key|Keys]) -> + Info = verify_info1(Info0, Key), + verify_info(Info, Keys). + +verify_info1(Info0, Key) when is_atom(Key) -> + case lists:keydelete(Key, 1, Info0) of + Info0 -> + ?FAIL({missing_info, Key}); + Info -> + Info + end; +verify_info1(Info0, {Key, SubKeys}) when is_atom(Key) andalso is_list(SubKeys) -> + case lists:keysearch(Key, 1, Info0) of + false -> + ?FAIL({missing_info, Key}); + {value, {Key, SubInfo}} -> + case verify_subinfo(SubInfo, SubKeys) of + ok -> + lists:keydelete(Key, 1, Info0); + {error, MissingSubKeyOrKeys} -> + ?FAIL({missing_info, {Key, MissingSubKeyOrKeys}}) + end + end. + +verify_subinfo(_, []) -> + ok; +verify_subinfo([], Keys) -> + {error, Keys}; +verify_subinfo(Info0, [Key|Keys]) -> + case lists:keydelete(Key, 1, Info0) of + Info0 -> + {error, Key}; + Info -> + verify_subinfo(Info, Keys) + end. + +verify_old_info(Info) -> + Keys = [vsns, subagents, loaded_mibs, + tree_size_bytes, process_memory, db_memory], + verify_old_info(Keys, Info). + +verify_old_info([], _) -> + ok; +verify_old_info([Key|Keys], Info) -> + case lists:keymember(Key, 1, Info) of + true -> + verify_old_info(Keys, Info); + false -> + ?FAIL({missing_old_info, Key}) + end. + +%% string used in index +is(S) -> [length(S) | S]. + +try_test(Func) -> + snmp_agent_test_lib:try_test(?MODULE, Func). + +try_test(Func, A) -> + snmp_agent_test_lib:try_test(?MODULE, Func, A). + +try_test(Func, A, Opts) -> + snmp_agent_test_lib:try_test(?MODULE, Func, A, Opts). + + +%% Test manager wrapperfunctions: +g(Oids) -> snmp_test_mgr:g(Oids). +gn() -> snmp_test_mgr:gn(). +gn(OidsOrN) -> snmp_test_mgr:gn(OidsOrN). +gb(NR, MR, Oids) -> snmp_test_mgr:gb(NR, MR, Oids). +s(VAV) -> snmp_test_mgr:s(VAV). + +expect(A, B) -> snmp_agent_test_lib:expect(A, B). +expect(A, B, C) -> snmp_agent_test_lib:expect(A, B, C). +expect(A, B, C, D) -> snmp_agent_test_lib:expect(A, B, C, D). +expect(A, B, C, D, E, F) -> snmp_agent_test_lib:expect(A, B, C, D, E, F). + +get_req(Id, Vars) -> + snmp_agent_test_lib:get_req(Id, Vars). + +get_next_req(Vars) -> + snmp_agent_test_lib:get_next_req(Vars). + + +start_node(Name) -> + snmp_agent_test_lib:start_node(Name). + +stop_node(Node) -> + snmp_agent_test_lib:stop_node(Node). + + +%%%----------------------------------------------------------------- +%%% Configuration +%%%----------------------------------------------------------------- +delete_files(Config) -> + snmp_agent_test_lib:delete_files(Config). + +config(Vsns, MgrDir, AgentDir, MIp, AIp) -> + snmp_agent_test_lib:config(Vsns, MgrDir, AgentDir, MIp, AIp). + +update_usm(Vsns, Dir) -> + snmp_agent_test_lib:update_usm(Vsns, Dir). + +update_usm_mgr(Vsns, Dir) -> + snmp_agent_test_lib:update_usm_mgr(Vsns, Dir). + +rewrite_usm_mgr(Dir, ShaKey, DesKey) -> + snmp_agent_test_lib:rewrite_usm_mgr(Dir, ShaKey, DesKey). + +reset_usm_mgr(Dir) -> + snmp_agent_test_lib:reset_usm_mgr(Dir). + +update_community(Vsns, DIr) -> + snmp_agent_test_lib:update_community(Vsns, DIr). + +update_vacm(Vsn, Dir) -> + snmp_agent_test_lib:update_vacm(Vsn, Dir). + +write_community_conf(Dir, Conf) -> + snmp_agent_test_lib:write_community_conf(Dir, Conf). + +write_target_addr_conf(Dir, Conf) -> + snmp_agent_test_lib:write_target_addr_conf(Dir, Conf). + +write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> + snmp_agent_test_lib:write_target_addr_conf(Dir, ManagerIp, UDP, Vsns). + +rewrite_target_addr_conf(Dir, NewPort) -> + snmp_agent_test_lib:rewrite_target_addr_conf(Dir, NewPort). + + +reset_target_addr_conf(Dir) -> + snmp_agent_test_lib:reset_target_addr_conf(Dir). + +write_target_params_conf(Dir, Vsns) -> + snmp_agent_test_lib:write_target_params_conf(Dir, Vsns). + +rewrite_target_params_conf(Dir, SecName, SecLevel) -> + snmp_agent_test_lib:rewrite_target_params_conf(Dir, SecName, SecLevel). + +reset_target_params_conf(Dir) -> + snmp_agent_test_lib:reset_target_params_conf(Dir). + +write_notify_conf(Dir) -> + snmp_agent_test_lib:write_notify_conf(Dir). + +write_view_conf(Dir) -> + snmp_agent_test_lib:write_view_conf(Dir). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +copy_file(From, To) -> + snmp_agent_test_lib:copy_file(From, To). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +display_memory_usage() -> + Info = snmpa:info(snmp_master_agent), + AMU = display_agent_memory_uasge(Info), + NIMU = display_net_if_memory_usage(Info), + NSMU = display_note_store_memory_usage(Info), + SSMU = display_symbolic_store_memory_usage(Info), + LDBMU = display_local_db_memory_usage(Info), + MSMU = display_mib_server_memory_usage(Info), + ?INF("Memory usage: ~n" ++ + AMU ++ NIMU ++ NSMU ++ SSMU ++ LDBMU ++ MSMU, []), + ok. + +display_agent_memory_uasge(Info) -> + AgentInfo = lists_key1search(agent, Info), + ProcMem = + lists_key1search([process_memory,master_agent], AgentInfo), + WProcMem = + lists_key1search([process_memory,worker], AgentInfo), + SWProcMem = + lists_key1search([process_memory,set_worker], AgentInfo), + TabSize = + lists_key1search([db_memory,agent], AgentInfo), + CCSize = + lists_key1search([db_memory,community_cache], AgentInfo), + VacmSize = + lists_key1search([db_memory,vacm], AgentInfo), + lists:flatten( + io_lib:format(" Agent memory usage: " + "~n Master process memory size: ~p" + "~n Worker process memory size: ~p" + "~n Set-worker process memory size: ~p" + "~n Agent tab size: ~p" + "~n Community cache size: ~p" + "~n Vacm tab size: ~p" + "~n", + [ProcMem, WProcMem, SWProcMem, + TabSize, CCSize, VacmSize])). + +display_net_if_memory_usage(Info) -> + NiInfo = lists_key1search(net_if, Info), + ProcMem = lists_key1search(process_memory, NiInfo), + lists:flatten( + io_lib:format(" Net if memory usage: " + "~n Process memory size: ~p" + "~n",[ProcMem])). + +display_note_store_memory_usage(Info) -> + NsInfo = lists_key1search(note_store, Info), + ProcMem = lists_key1search([process_memory,notes], NsInfo), + ProcTmrMem = lists_key1search([process_memory,timer], NsInfo), + TabSize = lists_key1search([db_memory,notes], NsInfo), + lists:flatten( + io_lib:format(" Note store memory usage: " + "~n Notes process memory size: ~p" + "~n Timer process memory size: ~p" + "~n Notes tab size: ~p" + "~n", + [ProcMem, ProcTmrMem, TabSize])). + + display_symbolic_store_memory_usage(Info) -> + SsInfo = lists_key1search(symbolic_store, Info), + ProcMem = lists_key1search(process_memory, SsInfo), + DbMem = lists_key1search(db_memory, SsInfo), + lists:flatten( + io_lib:format(" Symbolic store memory usage: " + "~n Process memory size: ~p" + "~n DB size: ~p" + "~n", + [ProcMem, DbMem])). + +display_local_db_memory_usage(Info) -> + LdInfo = lists_key1search(local_db, Info), + ProcMem = lists_key1search(process_memory, LdInfo), + EtsSize = lists_key1search([db_memory,ets], LdInfo), + DetsSize = lists_key1search([db_memory,dets], LdInfo), + lists:flatten( + io_lib:format(" Local DB memory usage: " + "~n Process memory size: ~p" + "~n DB [ets] size: ~p" + "~n DB [dets] size: ~p" + "~n", + [ProcMem, EtsSize, DetsSize])). + +display_mib_server_memory_usage(Info) -> + MibInfo = lists_key1search(mib_server, Info), + ProcMem = lists_key1search(process_memory, MibInfo), + TreeSize = lists_key1search(tree_size_bytes, MibInfo), + MibDbSize = lists_key1search([db_memory,mib], MibInfo), + NodeDbSize = lists_key1search([db_memory,node], MibInfo), + TreeDbSize = lists_key1search([db_memory,tree], MibInfo), + lists:flatten( + io_lib:format(" MIB server memory usage: " + "~n Process memory size: ~p" + "~n Tree size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p" + "~n", + [ProcMem, TreeSize, MibDbSize, NodeDbSize, TreeDbSize])). + +lists_key1search([], Res) -> + Res; +lists_key1search([Key|Keys], List) when is_atom(Key) andalso is_list(List) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + lists_key1search(Keys, Val); + false -> + undefined + end; +lists_key1search(Key, List) when is_atom(Key) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + Val; + false -> + undefined + end. + + +regs() -> + lists:sort(registered()). + diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl new file mode 100644 index 0000000000..31b375efa9 --- /dev/null +++ b/lib/snmp/test/snmp_agent_test_lib.erl @@ -0,0 +1,1480 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_agent_test_lib). + + +-export([ + start_v1_agent/1, start_v1_agent/2, + start_v2_agent/1, start_v2_agent/2, + start_v3_agent/1, start_v3_agent/2, + start_bilingual_agent/1, start_bilingual_agent/2, + start_mt_agent/1, start_mt_agent/2, + stop_agent/1, + + start_sup/0, stop_sup/2, + start_subagent/3, stop_subagent/1, + start_sub_sup/1, start_sub_sup/2, + + start_node/1, stop_node/1, + + load_master/1, load_master_std/1, unload_master/1, + loaded_mibs/0, unload_mibs/1, + + get_req/2, get_next_req/1, + + config/5, + delete_files/1, + copy_file/2, + update_usm/2, + update_usm_mgr/2, rewrite_usm_mgr/3, reset_usm_mgr/1, + update_community/2, + update_vacm/2, + write_community_conf/2, + write_target_addr_conf/2, write_target_addr_conf/4, + rewrite_target_addr_conf/2, reset_target_addr_conf/1, + write_target_params_conf/2, rewrite_target_params_conf/3, + reset_target_params_conf/1, + write_notify_conf/1, write_view_conf/1, + + display_memory_usage/0, + + init_all/1, finish_all/1, + init_case/1, + try_test/2, try_test/3, try_test/4, + expect/2, expect/3, expect/4, expect/6, + + regs/0, + rpc/3 + ]). + +%% Internal exports +-export([wait/5, run/4]). + +-include_lib("kernel/include/file.hrl"). +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). + +-define(TRAP_UDP, 5000). + +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + +-define(v1_2_3(V1,V2,V3), + case get(vsn) of + v1 -> V1; + v2 -> V2; + _ -> V3 + end). + + +%%%----------------------------------------------------------------- +%%% The test case structure is as follows: +%%% +%%% init_all - starts mnesia, +%%% +%%% init_v1 - starts agent +%%% simple +%%% big - e.g. starts/stops subagent, load/unloads mibs +%%% init_mul +%%% mul_get +%%% mul_set +%%% <etc> +%%% finish_mul +%%% <etc> +%%% finish_v1 +%%% +%%% init_v2 - starts agent +%%% finish_v2 +%%% +%%% init_bilingual - starts agent +%%% finish_bilingual +%%% +%%% finish_all +%%% +%%% There is still one problem with these testsuites. If one test +%%% fails, it may not be possible to run some other cases, as it +%%% may have e.g. created some row or loaded some table, that it +%%% didn't undo (since it failed). +%%%----------------------------------------------------------------- + +init_all(Config0) when is_list(Config0) -> + ?LOG("init_all -> entry with" + "~n Config0: ~p",[Config0]), + + %% -- + %% Fix config: + %% + + DataDir0 = ?config(data_dir, Config0), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + Config1 = lists:keydelete(data_dir, 1, Config0), + Config = [{data_dir, DataDir3 ++ "/"}|Config1], + + %% -- + %% Start nodes + %% + + ?line {ok, SaNode} = start_node(snmp_sa), + ?line {ok, MgrNode} = start_node(snmp_mgr), + + + %% -- + %% Create necessary files + %% + + PrivDir = ?config(priv_dir, Config), + ?DBG("init_all -> PrivDir ~p", [PrivDir]), + + TopDir = filename:join(PrivDir, snmp_agent_test), + case file:make_dir(TopDir) of + ok -> + ok; + {error, eexist} -> + ok; + Error -> + ?FAIL({failed_creating_subsuite_top_dir, Error}) + end, + + DataDir = ?config(data_dir, Config), + ?DBG("init_all -> DataDir ~p", [DataDir]), + + ?line ok = file:make_dir(MgrDir = filename:join(TopDir, "mgr_dir/")), + ?DBG("init_all -> MgrDir ~p", [MgrDir]), + + ?line ok = file:make_dir(AgentDir = filename:join(TopDir, "agent_dir/")), + ?DBG("init_all -> AgentDir ~p", [AgentDir]), + + ?line ok = file:make_dir(SaDir = filename:join(TopDir, "sa_dir/")), + ?DBG("init_all -> SaDir ~p", [SaDir]), + + + %% -- + %% Start and initiate mnesia + %% + + ?DBG("init_all -> load application mnesia", []), + ?line ok = application:load(mnesia), + + ?DBG("init_all -> load application mnesia on node ~p", [SaNode]), + ?line ok = rpc:call(SaNode, application, load, [mnesia]), + + ?DBG("init_all -> application mnesia: set_env dir",[]), + ?line application_controller:set_env(mnesia, dir, + filename:join(TopDir, "Mnesia1")), + + ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]), + ?line rpc:call(SaNode, application_controller, set_env, + [mnesia, dir, filename:join(TopDir, "Mnesia2")]), + + ?DBG("init_all -> create mnesia schema",[]), + ?line ok = mnesia:create_schema([SaNode, node()]), + + ?DBG("init_all -> start application mnesia",[]), + ?line ok = application:start(mnesia), + + ?DBG("init_all -> start application mnesia on ~p",[SaNode]), + ?line ok = rpc:call(SaNode, application, start, [mnesia]), + Ip = ?LOCALHOST(), + [{snmp_sa, SaNode}, + {snmp_mgr, MgrNode}, + {agent_dir, AgentDir ++ "/"}, + {mgr_dir, MgrDir ++ "/"}, + {sa_dir, SaDir ++ "/"}, + {mib_dir, DataDir}, + {ip, Ip} | + Config]. + + +finish_all(Config) when is_list(Config) -> + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + stop_node(SaNode), + stop_node(MgrNode), + application:stop(mnesia). + + +%% --- This one *must* be run first in each case --- + +init_case(Config) when is_list(Config) -> + ?DBG("init_case -> entry with" + "~n Config: ~p", [Config]), + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + MasterNode = node(), + + SaHost = ?HOSTNAME(SaNode), + MgrHost = ?HOSTNAME(MgrNode), + MasterHost = ?HOSTNAME(MasterNode), + {ok, MasterIP} = snmp_misc:ip(MasterHost), + {ok, MIP} = snmp_misc:ip(MgrHost), + {ok, SIP} = snmp_misc:ip(SaHost), + + + put(mgr_node, MgrNode), + put(sa_node, SaNode), + put(master_node, MasterNode), + put(sa_host, SaHost), + put(mgr_host, MgrHost), + put(master_host, MasterHost), + put(mip, tuple_to_list(MIP)), + put(masterip, tuple_to_list(MasterIP)), + put(sip, tuple_to_list(SIP)), + + MibDir = ?config(mib_dir, Config), + put(mib_dir, MibDir), + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + put(std_mib_dir, StdM), + + MgrDir = ?config(mgr_dir, Config), + put(mgr_dir, MgrDir), + + put(vsn, ?config(vsn, Config)), + ?DBG("init_case -> exit with" + "~n MasterNode: ~p" + "~n SaNode: ~p" + "~n MgrNode: ~p" + "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]), + {SaNode, MgrNode, MibDir}. + + +%%%-------------------------------------------------- +%%% Used to test the standard mib with our +%%% configuration. +%%%-------------------------------------------------- + +try_test(Mod, Func) -> + call(get(mgr_node), ?MODULE, run, [Mod, Func, [], []]). + +try_test(Mod, Func, A) -> + call(get(mgr_node), ?MODULE, run, [Mod, Func, A, []]). + +try_test(Mod, Func, A, Opts) -> + call(get(mgr_node), ?MODULE, run, [Mod, Func, A, Opts]). + +call(N,M,F,A) -> + ?DBG("call -> entry with~n" + " N: ~p~n" + " M: ~p~n" + " F: ~p~n" + " A: ~p~n" + " when~n" + " get(): ~p", + [N,M,F,A,get()]), + spawn(N, ?MODULE, wait, [self(),get(),M,F,A]), + receive + {done, {'EXIT', Rn}, Loc} -> + ?DBG("call -> done with exit: " + "~n Rn: ~p" + "~n Loc: ~p", [Rn, Loc]), + put(test_server_loc, Loc), + exit(Rn); + {done, Ret, Zed} -> + ?DBG("call -> done:" + "~n Ret: ~p" + "~n Zed: ~p", [Ret, Zed]), + Ret + end. + +wait(From, Env, M, F, A) -> + ?DBG("wait -> entry with" + "~n From: ~p" + "~n Env: ~p" + "~n M: ~p" + "~n F: ~p" + "~n A: ~p", [From, Env, M, F, A]), + lists:foreach(fun({K,V}) -> put(K,V) end, Env), + Rn = (catch apply(M, F, A)), + ?DBG("wait -> Rn: ~n~p", [Rn]), + From ! {done, Rn, get(test_server_loc)}, + exit(Rn). + +run(Mod, Func, Args, Opts) -> + ?DBG("run -> entry with" + "~n Mod: ~p" + "~n Func: ~p" + "~n Args: ~p" + "~n Opts: ~p", [Mod, Func, Args, Opts]), + M = get(mib_dir), + Dir = get(mgr_dir), + User = snmp_misc:get_option(user, Opts, "all-rights"), + SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv), + EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"), + CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID), + Community = snmp_misc:get_option(community, Opts, "all-rights"), + ?DBG("run -> start crypto app",[]), + Crypto = case os:type() of + vxworks -> + no_crypto; + _ -> + ?CRYPTO_START() + end, + ?DBG("run -> Crypto: ~p", [Crypto]), + catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + Vsn = get(vsn), + ?DBG("run -> config:" + "~n M: ~p" + "~n Vsn: ~p" + "~n Dir: ~p" + "~n User: ~p" + "~n SecLevel: ~p" + "~n EngineID: ~p" + "~n CtxEngineID: ~p" + "~n Community: ~p" + "~n StdM: ~p", + [M,Vsn,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]), + case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()}, + {packet_server_debug,true}, + {debug,true}, + {agent, get(master_host)}, + {agent_udp, 4000}, + {trap_udp, 5000}, + {recbuf,65535}, + quiet, + Vsn, + {community, Community}, + {user, User}, + {sec_level, SecLevel}, + {engine_id, EngineID}, + {context_engine_id, CtxEngineID}, + {dir, Dir}, + {mibs, mibs(StdM, M)}]) of + {ok, _Pid} -> + case (catch apply(Mod, Func, Args)) of + {'EXIT', Reason} -> + catch snmp_test_mgr:stop(), + ?FAIL({apply_failed, {Mod, Func, Args}, Reason}); + Res -> + catch snmp_test_mgr:stop(), + Res + end; + Err -> + io:format("Error starting manager: ~p\n", [Err]), + catch snmp_test_mgr:stop(), + ?line ?FAIL({mgr_start, Err}) + end. + + +%% --------------------------------------------------------------- +%% --- --- +%% --- Start the agent --- +%% --- --- +%% --------------------------------------------------------------- + +start_v1_agent(Config) when is_list(Config) -> + start_agent(Config, [v1]). + +start_v1_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v1], Opts). + +start_v2_agent(Config) when is_list(Config) -> + start_agent(Config, [v2]). + +start_v2_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v2], Opts). + +start_v3_agent(Config) when is_list(Config) -> + start_agent(Config, [v3]). + +start_v3_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v3], Opts). + +start_bilingual_agent(Config) when is_list(Config) -> + start_agent(Config, [v1,v2]). + +start_bilingual_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v1,v2], Opts). + +start_mt_agent(Config) when is_list(Config) -> + start_agent(Config, [v2], [{snmp_multi_threaded, true}]). + +start_mt_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> + start_agent(Config, [v2], [{snmp_multi_threaded, true}|Opts]). + +start_agent(Config, Vsns) -> + start_agent(Config, Vsns, []). +start_agent(Config, Vsns, Opts) -> + ?LOG("start_agent -> entry (~p) with" + "~n Config: ~p" + "~n Vsns: ~p" + "~n Opts: ~p",[node(), Config, Vsns, Opts]), + + ?line AgentDir = ?config(agent_dir, Config), + ?line SaNode = ?config(snmp_sa, Config), + +%% AgentConfig = +%% [{agent_type, master}, +%% %% {multi_threaded, MultiT}, +%% %% {priority, Prio}, +%% %% {error_report_mod, ErrorReportMod}, +%% {versions, Vsns}, +%% {db_dir, AgentDir}, +%% %% {db_init_error, DbInitError}, +%% %% {set_mechanism, SetModule}, +%% %% {authentication_service, AuthModule}, +%% {audit_trail_log, [{type, read_write}, +%% {dir, AgentDir}, +%% {size, {10240, 10}}, +%% {repair, true}]}, +%% {config, [{verbosity, info}, +%% {dir, AgentDir}, +%% {force_load, false}]}, +%% {mibs, Mibs}, +%% %% {mib_storage, MibStorage}, +%% {local_db, []}, +%% {mib_server, []}, +%% {symbolic_store, []}, +%% {note_store, []}, +%% {net_if, []}, +%% %% {supervisor, SupOpts} +%% ], + + app_env_init(vsn_init(Vsns) ++ + [{audit_trail_log, read_write_log}, + {audit_trail_log_dir, AgentDir}, + {audit_trail_log_size, {10240, 10}}, + {force_config_reload, false}, + {snmp_agent_type, master}, + {snmp_config_dir, AgentDir}, + {snmp_db_dir, AgentDir}, + {snmp_local_db_auto_repair, true}, + {snmp_local_db_verbosity, log}, + {snmp_master_agent_verbosity, trace}, + {snmp_supervisor_verbosity, trace}, + {snmp_mibserver_verbosity, log}, + {snmp_symbolic_store_verbosity, log}, + {snmp_note_store_verbosity, log}, + {snmp_net_if_verbosity, trace}], + Opts), + + + process_flag(trap_exit,true), + + {ok, AppSup} = snmp_app_sup:start_link(), + unlink(AppSup), + ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]), + + ?DBG("start_agent -> start master agent (old style)",[]), + ?line Sup = start_sup(), + + ?DBG("start_agent -> unlink from supervisor",[]), + ?line unlink(Sup), + ?line SaDir = ?config(sa_dir, Config), + ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]), + ?line {ok, Sub} = start_sub_sup(SaNode, SaDir), + ?DBG("start_agent -> done",[]), + ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config]. + + +vsn_init(Vsn) -> + vsn_init([v1,v2,v3], Vsn, []). + +vsn_init([], _Vsn, Acc) -> + Acc; +vsn_init([V|Vsns], Vsn, Acc) -> + case lists:member(V, Vsn) of + true -> + vsn_init(Vsns, Vsn, [{V, true}|Acc]); + false -> + vsn_init(Vsns, Vsn, [{V, false}|Acc]) + end. + +app_env_init(Env0, Opts) -> + ?DBG("app_env_init -> unload snmp",[]), + ?line application:unload(snmp), + ?DBG("app_env_init -> load snmp",[]), + ?line application:load(snmp), + ?DBG("app_env_init -> initiate (snmp) application env",[]), + F1 = fun({Key, Val} = New, Acc0) -> + ?DBG("app_env_init -> " + "updating setting ~p to ~p", [Key, Val]), + case lists:keyreplace(Key, 1, Acc0, New) of + Acc0 -> + [New|Acc0]; + Acc -> + Acc + end + end, + Env = lists:foldr(F1, Env0, Opts), + ?DBG("app_env_init -> Env: ~p",[Env]), + F2 = fun({Key,Val}) -> + ?DBG("app_env_init -> setting ~p to ~p",[Key, Val]), + application_controller:set_env(snmp, Key, Val) + end, + lists:foreach(F2, Env). + + +stop_agent(Config) when is_list(Config) -> + ?LOG("stop_agent -> entry with" + "~n Config: ~p",[Config]), + + {Sup, Par} = ?config(snmp_sup, Config), + ?DBG("stop_agent -> attempt to stop (sup) ~p" + "~n Sup: ~p" + "~n Par: ~p", + [Sup, + (catch process_info(Sup)), + (catch process_info(Par))]), + + Info = agent_info(Sup), + ?DBG("stop_agent -> Agent info: " + "~n ~p", [Info]), + + stop_sup(Sup, Par), + + {Sup2, Par2} = ?config(snmp_sub, Config), + ?DBG("stop_agent -> attempt to stop (sub) ~p" + "~n Sup2: ~p" + "~n Par2: ~p", + [Sup2, + (catch process_info(Sup2)), + (catch process_info(Par2))]), + stop_sup(Sup2, Par2), + + ?DBG("stop_agent -> done - now cleanup config", []), + C1 = lists:keydelete(snmp_sup, 1, Config), + lists:keydelete(snmp_sub, 1, C1). + + +start_sup() -> + case (catch snmpa_app:start(normal)) of + {ok, S} -> + ?DBG("start_agent -> started, Sup: ~p",[S]), + S; + + Else -> + ?DBG("start_agent -> unknown result: ~n~p",[Else]), + %% Get info about the apps we depend on + ?FAIL({start_failed,Else, ?IS_MNESIA_RUNNING()}) + end. + +stop_sup(Pid, _) when (node(Pid) =:= node()) -> + case (catch process_info(Pid)) of + PI when is_list(PI) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + exit(Pid, kill), + await_stopped(Pid, Ref); + {'EXIT', _Reason} -> + ?LOG("stop_sup -> ~p not running", [Pid]), + ok + end; +stop_sup(Pid, _) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + ?LOG("stop_sup -> Ref: ~p", [Ref]), + %% Pid ! {'EXIT', Parent, shutdown}, % usch + exit(Pid, kill), + await_stopped(Pid, Ref). + +await_stopped(Pid, Ref) -> + receive + {'DOWN', Ref, process, Pid, _Reason} -> + ?DBG("received down message for ~p", [Pid]), + ok + after 10000 -> + ?INF("await_stopped -> timeout for ~p",[Pid]), + erlang:demonitor(Ref), + ?FAIL({failed_stop,Pid}) + end. + + +%% --- start subagent supervisor --- + +start_sub_sup(Node, Dir) -> + rpc:call(Node, ?MODULE, start_sub_sup, [Dir]). + +start_sub_sup(Dir) -> + ?DBG("start_sub -> entry",[]), + Opts = [{db_dir, Dir}, + {supervisor, [{verbosity, trace}]}], + {ok, P} = snmpa_supervisor:start_sub_sup(Opts), + unlink(P), + {ok, {P, self()}}. + + +%% --- start and stop subagents --- + +start_subagent(SaNode, RegTree, Mib) -> + ?DBG("start_subagent -> entry with" + "~n SaNode: ~p" + "~n RegTree: ~p" + "~n Mib: ~p", [SaNode, RegTree, Mib]), + MA = whereis(snmp_master_agent), + ?DBG("start_subagent -> MA: ~p", [MA]), + MibDir = get(mib_dir), + Mib1 = join(MibDir,Mib), + Mod = snmpa_supervisor, + Func = start_sub_agent, + Args = [MA, RegTree, [Mib1]], + case rpc:call(SaNode, Mod, Func, Args) of + {ok, SA} -> + ?DBG("start_subagent -> SA: ~p", [SA]), + {ok, SA}; + Error -> + ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]}) + end. + +stop_subagent(SA) -> + ?DBG("stop_subagent -> entry with" + "~n SA: ~p", [SA]), + rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]). + + +mibs(StdMibDir,MibDir) -> + [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")), + join(MibDir, "OLD-SNMPEA-MIB.bin"), + join(StdMibDir, "SNMP-FRAMEWORK-MIB"), + join(StdMibDir, "SNMP-MPD-MIB"), + join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"), + join(StdMibDir, "SNMP-USER-BASED-SM-MIB"), + join(StdMibDir, "SNMP-TARGET-MIB"), + join(StdMibDir, "SNMP-NOTIFICATION-MIB"), + join(MibDir, "Klas1.bin"), + join(MibDir, "Klas2.bin"), + join(MibDir, "Klas3.bin"), + join(MibDir, "Klas4.bin"), + join(MibDir, "SA-MIB.bin"), + join(MibDir, "TestTrap.bin"), + join(MibDir, "Test1.bin"), + join(MibDir, "Test2.bin"), + join(MibDir, "TestTrapv2.bin")]. + +join(D,F) -> + filename:join(D,F). + + +%% --- various mib load/unload functions --- + +load_master(Mib) -> + ?DBG("load_master -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]). + +load_master_std(Mib) -> + ?DBG("load_master_std -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]). + +unload_master(Mib) -> + ?DBG("unload_master -> entry with" + "~n Mib: ~p", [Mib]), + ok = snmpa:unload_mibs(snmp_master_agent, [Mib]). + +loaded_mibs() -> + ?DBG("loaded_mibs -> entry",[]), + Info = snmpa:info(snmp_master_agent), + {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info), + [atom_to_list(Mib) || {Mib,_,_} <- Mibs]. + +unload_mibs(Mibs) -> + ?DBG("unload_mibs -> entry with" + "~n Mibs: ~p", [Mibs]), + ok = snmpa:unload_mibs(snmp_master_agent, Mibs). + + +agent_info(Sup) -> + ?DBG("agent_info -> entry with" + "~n Sup: ~p", [Sup]), + rpc:call(node(Sup), snmpa, info, []). + + +%% --- + +expect(Id, A) -> + Fun = fun() -> do_expect(A) end, + expect2(Id, Fun). + +expect(Id, A, B) -> + Fun = fun() -> do_expect(A, B) end, + expect2(Id, Fun). + +expect(Id, A, B, C) -> + Fun = fun() -> do_expect(A, B, C) end, + expect2(Id, Fun). + +expect(Id, A, B, C, D, E) -> + Fun = fun() -> do_expect(A, B, C, D, E) end, + expect2(Id, Fun). + +expect2(Id, F) -> + io:format("~w:expect2 -> entry with" + "~n Id: ~w" + "~n", [?MODULE, Id]), + case F() of + {error, Reason} -> + {error, Id, Reason}; + Else -> + io:format("~w:expect2 -> " + "~n Id: ~w" + "~n Else: ~p" + "~n", [?MODULE, Id, Else]), + Else + end. + + +%% ---------------------------------------------------------------------- + +get_timeout() -> + get_timeout(os:type()). + +get_timeout(vxworks) -> 7000; +get_timeout(_) -> 3500. + +receive_pdu(To) -> + receive + {snmp_pdu, PDU} when is_record(PDU, pdu) -> + PDU + after To -> + {error, timeout} + end. + +receive_trap(To) -> + receive + {snmp_pdu, PDU} when is_record(PDU, trappdu) -> + PDU + after To -> + {error, timeout} + end. + + +do_expect(Expect) when is_atom(Expect) -> + do_expect({Expect, get_timeout()}); + +do_expect({any_pdu, To}) + when is_integer(To) orelse (To =:= infinity) -> + io:format("~w:do_expect(any_pdu) -> entry with" + "~n To: ~w" + "~n", [?MODULE, To]), + receive_pdu(To); + +do_expect({any_trap, To}) -> + io:format("~w:do_expect(any_trap) -> entry with" + "~n To: ~w" + "~n", [?MODULE, To]), + receive_trap(To); + +do_expect({timeout, To}) -> + io:format("~w:do_expect(timeout) -> entry with" + "~n To: ~w" + "~n", [?MODULE, To]), + receive + X -> + {error, {unexpected, X}} + after + To -> + ok + end; + +do_expect({Err, To}) + when is_atom(Err) andalso (is_integer(To) orelse (To =:= infinity)) -> + do_expect({{error, Err}, To}); + +do_expect({error, Err}) when is_atom(Err) -> + Check = fun(_, R) -> R end, + do_expect2(Check, any, Err, any, any, get_timeout()); +do_expect({{error, Err}, To}) -> + Check = fun(_, R) -> R end, + do_expect2(Check, any, Err, any, any, To); + +%% exp_varbinds() -> [exp_varbind()] +%% exp_varbind() -> any | {Oid, any} | {Oid, Value} +%% Oid -> [integer()] +%% Value -> term() +%% ExpVBs -> exp_varbinds() | {VbsCondition, exp_varbinds()} +do_expect(ExpVBs) -> + Check = fun(_, R) -> R end, + do_expect2(Check, 'get-response', noError, 0, ExpVBs, get_timeout()). + + +do_expect(v2trap, ExpVBs) -> + Check = fun(_, R) -> R end, + do_expect2(Check, 'snmpv2-trap', noError, 0, ExpVBs, get_timeout()); + + +do_expect(report, ExpVBs) -> + Check = fun(_, R) -> R end, + do_expect2(Check, 'report', noError, 0, ExpVBs, get_timeout()); + + +do_expect(inform, ExpVBs) -> + do_expect({inform, true}, ExpVBs); + +do_expect({inform, false}, ExpVBs) -> + io:format("~w:do_expect(inform, false) -> entry with" + "~n ExpVBs: ~p" + "~n", [?MODULE, ExpVBs]), + Check = fun(_, R) -> R end, + do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()); + +do_expect({inform, true}, ExpVBs) -> + io:format("~w:do_expect(inform, true) -> entry with" + "~n ExpVBs: ~p" + "~n", [?MODULE, ExpVBs]), + Check = + fun(PDU, ok) -> + RespPDU = PDU#pdu{type = 'get-response', + error_status = noError, + error_index = 0}, + snmp_test_mgr:rpl(RespPDU), + ok; + (_, Err) -> + Err + end, + do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()); + +do_expect({inform, {error, EStat, EIdx}}, ExpVBs) + when is_atom(EStat) andalso is_integer(EIdx) -> + Check = + fun(PDU, ok) -> + RespPDU = PDU#pdu{type = 'get-response', + error_status = EStat, + error_index = EIdx}, + snmp_test_mgr:rpl(RespPDU), + ok; + (_, Err) -> + Err + end, + do_expect2(Check, 'inform-request', noError, 0, ExpVBs, get_timeout()). + + +do_expect(Err, Idx, ExpVBs) -> + do_expect(Err, Idx, ExpVBs, get_timeout()). + +do_expect(Err, Idx, ExpVBs, To) + when is_atom(Err) andalso + (is_integer(Idx) orelse is_list(Idx) orelse (Idx == any)) -> + Check = fun(_, R) -> R end, + do_expect2(Check, 'get-response', Err, Idx, ExpVBs, To). + + +do_expect(Type, Enterp, Generic, Specific, ExpVBs) -> + do_expect(Type, Enterp, Generic, Specific, ExpVBs, 3500). + +do_expect(trap, Enterp, Generic, Specific, ExpVBs, To) -> + io:format("~w:do_expect(trap) -> entry with" + "~n Enterp: ~w" + "~n Generic: ~w" + "~n Specific: ~w" + "~n ExpVBs: ~w" + "~n To: ~w" + "~nwhen" + "~n Time: ~w" + "~n", [?MODULE, Enterp, Generic, Specific, ExpVBs, To, t()]), + PureE = purify_oid(Enterp), + case receive_trap(To) of + #trappdu{enterprise = PureE, + generic_trap = Generic, + specific_trap = Specific, + varbinds = VBs} -> + check_vbs(purify_oids(ExpVBs), VBs); + + #trappdu{enterprise = Ent2, + generic_trap = G2, + specific_trap = Spec2, + varbinds = VBs} -> + {error, {unexpected_trap, + {PureE, Generic, Specific, ExpVBs}, + {Ent2, G2, Spec2, VBs}}}; + + Error -> + Error + end. + + +do_expect2(Check, Type, Err, Idx, ExpVBs, To) + when is_function(Check) andalso + is_atom(Type) andalso + is_atom(Err) andalso + (is_integer(Idx) orelse is_list(Idx) orelse (Idx =:= any)) andalso + (is_list(ExpVBs) orelse (ExpVBs =:= any)) andalso + (is_integer(To) orelse (To =:= infinity)) -> + + io:format("~w:do_expect2 -> entry with" + "~n Type: ~w" + "~n Err: ~w" + "~n Idx: ~w" + "~n ExpVBs: ~w" + "~n To: ~w" + "~nwhen" + "~n Time: ~w" + "~n", [?MODULE, Type, Err, Idx, ExpVBs, To, t()]), + + case receive_pdu(To) of + + #pdu{type = Type, + error_status = Err, + error_index = Idx} when ExpVBs =:= any -> + ok; + + #pdu{type = Type, + request_id = ReqId, + error_status = Err2, + error_index = Idx} when ExpVBs =:= any -> + {error, {unexpected_error_status, Err, Err2, ReqId}}; + + #pdu{error_status = Err} when (Type =:= any) andalso + (Idx =:= any) andalso + (ExpVBs =:= any) -> + ok; + + #pdu{request_id = ReqId, + error_status = Err2} when (Type =:= any) andalso + (Idx =:= any) andalso + (ExpVBs =:= any) -> + {error, {unexpected_error_status, Err, Err2, ReqId}}; + + #pdu{type = Type, + error_status = Err} when (Idx =:= any) andalso + (ExpVBs =:= any) -> + ok; + + #pdu{type = Type, + request_id = ReqId, + error_status = Err2} when (Idx =:= any) andalso + (ExpVBs =:= any) -> + {error, {unexpected_error_status, Err, Err2, ReqId}}; + + #pdu{type = Type, + request_id = ReqId, + error_status = Err, + error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) -> + case lists:member(EI, Idx) of + true -> + ok; + false -> + {error, {unexpected_error_index, EI, Idx, ReqId}} + end; + + #pdu{type = Type, + request_id = ReqId, + error_status = Err2, + error_index = EI} when is_list(Idx) andalso (ExpVBs =:= any) -> + case lists:member(EI, Idx) of + true -> + {error, {unexpected_error_status, Err, Err2, ReqId}}; + false -> + {error, {unexpected_error, {Err, Idx}, {Err2, EI}, ReqId}} + end; + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Idx2} when ExpVBs =:= any -> + {error, + {unexpected_pdu, + {Type, Err, Idx}, {Type2, Err2, Idx2}, ReqId}}; + + #pdu{type = Type, + error_status = Err, + error_index = Idx, + varbinds = VBs} = PDU -> + Check(PDU, check_vbs(purify_oids(ExpVBs), VBs)); + + #pdu{type = Type, + error_status = Err, + varbinds = VBs} = PDU when Idx =:= any -> + Check(PDU, check_vbs(purify_oids(ExpVBs), VBs)); + + #pdu{type = Type, + request_id = ReqId, + error_status = Err, + error_index = EI, + varbinds = VBs} = PDU when is_list(Idx) -> + PureVBs = purify_oids(ExpVBs), + case lists:member(EI, Idx) of + true -> + Check(PDU, check_vbs(PureVBs, VBs)); + false -> + {error, {unexpected_error_index, Idx, EI, ReqId}} + end; + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Idx2, + varbinds = VBs2} -> + {error, + {unexpected_pdu, + {Type, Err, Idx, purify_oids(ExpVBs)}, + {Type2, Err2, Idx2, VBs2}, + ReqId}}; + + Error -> + Error + end. + + + +check_vbs([], []) -> + ok; +check_vbs(Exp, []) -> + {error, {to_few_vbs, Exp}}; +check_vbs([], VBs) -> + {error, {to_many_vbs, VBs}}; +check_vbs([any|Exp], [_|VBs]) -> + check_vbs(Exp, VBs); +check_vbs([{Oid, any}|Exp], [#varbind{oid = Oid}|VBs]) -> + check_vbs(Exp, VBs); +check_vbs([{Oid, Val}|Exp], [#varbind{oid = Oid, value = Val}|VBs]) -> + check_vbs(Exp, VBs); +check_vbs([{Oid, Val1}|_], [#varbind{oid = Oid, value = Val2}|_]) -> + {error, {unexpected_vb_value, Oid, Val1, Val2}}; +check_vbs([{Oid1, _}|_], [#varbind{oid = Oid2}|_]) -> + {error, {unexpected_vb_oid, Oid1, Oid2}}. + + +purify_oids({VbsCondition, VBs}) + when ((VbsCondition =:= true) orelse (VbsCondition =:= false)) andalso + is_list(VBs) -> + {VbsCondition, do_purify_oids(VBs)}; +purify_oids(VBs) when is_list(VBs) -> + do_purify_oids(VBs). + +do_purify_oids([]) -> + []; +do_purify_oids([{XOid, Q}|T]) -> + [{purify_oid(XOid), Q} | do_purify_oids(T)]. + + +purify_oid(Oid) -> + io:format("~w:purify_oid -> entry with" + "~n Oid: ~w" + "~n", + [?MODULE, Oid]), + case (catch snmp_test_mgr:purify_oid(Oid)) of + {error, Reason} -> + io:format("~w:purify_oid -> error: " + "~n Reason: ~p" + "~n", + [?MODULE, Reason]), + exit({malformed_oid, Reason}); + {ok, Oid2} when is_list(Oid2) -> + io:format("~w:purify_oid -> ok: " + "~n Oid2: ~p" + "~n", + [?MODULE, Oid2]), + Oid2; + Error -> + io:format("~w:purify_oid -> unexpected return value: " + "~n Error: ~p" + "~n", + [?MODULE, Error]), + exit({unexpected_purify_result, Error}) + + end. + + +%% ---------------------------------------------------------------------- + +get_req(Id, Vars) -> + ?DBG("get_req -> entry with" + "~n Id: ~p" + "~n Vars: ~p",[Id,Vars]), + snmp_test_mgr:g(Vars), + ?DBG("get_req -> await response",[]), + case snmp_test_mgr:get_response(Id, Vars) of + {ok, Val} -> + ?DBG("get_req -> response: ~p",[Val]), + Val; + {error, _, {ExpFmt, ExpArg}, {ActFmt, ActArg}} -> + ?DBG("get_req -> error for ~p: " + "~n " ++ ExpFmt ++ + "~n " ++ ActFmt, + [Id] ++ ExpArg ++ ActArg), + exit({unexpected_response, ExpArg, ActArg}); + Error -> + ?DBG("get_req -> error: ~n~p",[Error]), + exit({unknown, Error}) + end. + + +get_next_req(Vars) -> + ?DBG("get_next_req -> entry with" + "~n Vars: ~p",[Vars]), + snmp_test_mgr:gn(Vars), + ?DBG("get_next_req -> await response",[]), + Response = snmp_test_mgr:receive_response(), + ?DBG("get_next_req -> response: ~p",[Response]), + Response. + + +%% --- start and stop nodes --- + +start_node(Name) -> + ?LOG("start_node -> entry with" + "~n Name: ~p" + "~n when" + "~n hostname of this node: ~p", + [Name, list_to_atom(?HOSTNAME(node()))]), + Pa = filename:dirname(code:which(?MODULE)), + ?DBG("start_node -> Pa: ~p",[Pa]), + + Args = case init:get_argument('CC_TEST') of + {ok, [[]]} -> + " -pa /clearcase/otp/libraries/snmp/ebin "; + {ok, [[Path]]} -> + " -pa " ++ Path; + error -> + "" + end, + %% Do not use start_link!!! (the proc that calls this one is tmp) + ?DBG("start_node -> Args: ~p~n",[Args]), + A = Args ++ " -pa " ++ Pa, + case (catch ?START_NODE(Name, A)) of + {ok, Node} -> + %% Tell the test_server to not clean up things it never started. + ?DBG("start_node -> Node: ~p",[Node]), + {ok, Node}; + Else -> + ?ERR("start_node -> failed with(other): Else: ~p",[Else]), + ?line ?FAIL(Else) + end. + + +stop_node(Node) -> + ?LOG("stop_node -> Node: ~p",[Node]), + rpc:cast(Node, erlang, halt, []). + + +%%%----------------------------------------------------------------- +%%% Configuration +%%%----------------------------------------------------------------- + +config(Vsns, MgrDir, AgentDir, MIp, AIp) -> + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp, + ?TRAP_UDP, AIp, 4000, + "test"), + ?line case update_usm(Vsns, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsns, MgrDir); + false -> + ?line ok + end, + ?line update_community(Vsns, AgentDir), + ?line update_vacm(Vsns, AgentDir), + ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns), + ?line write_target_params_conf(AgentDir, Vsns), + ?line write_notify_conf(AgentDir), + ok. + +delete_files(Config) -> + Dir = ?config(agent_dir, Config), + {ok, List} = file:list_dir(Dir), + lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end, + List). + +update_usm(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + Conf = [{"agentEngine", "all-rights", "all-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"agentEngine", "no-rights", "no-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"agentEngine", "authMD5", "authMD5", zeroDotZero, + usmHMACMD5AuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "passwd_md5xxxxxx", ""}, + + {"agentEngine", "authSHA", "authSHA", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", ""}, + + {"agentEngine", "privDES", "privDES", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}, + + {"mgrEngine", "all-rights", "all-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"mgrEngine", "no-rights", "no-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"mgrEngine", "authMD5", "authMD5", zeroDotZero, + usmHMACMD5AuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "passwd_md5xxxxxx", ""}, + + {"mgrEngine", "authSHA", "authSHA", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", ""}, + + {"mgrEngine", "privDES", "privDES", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}], + ?line ok = snmp_config:update_agent_usm_config(Dir, Conf), + true; + false -> + false + end. + +update_usm_mgr(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + Conf = [{"agentEngine", "newUser", "newUser", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}, + + {"mgrEngine", "newUser", "newUser", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}], + + ?line ok = snmp_config:update_agent_usm_config(Dir, Conf), + true; + false -> + false + end. + +rewrite_usm_mgr(Dir, ShaKey, DesKey) -> + ?line ok = file:rename(filename:join(Dir,"usm.conf"), + filename:join(Dir,"usm.old")), + Conf = [{"agentEngine", "newUser", "newUser", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", ShaKey, DesKey}, + {"mgrEngine", "newUser", "newUser", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", ShaKey, DesKey}], + ok = snmp_config:write_agent_usm_config(Dir, "", Conf). + +reset_usm_mgr(Dir) -> + ?line ok = file:rename(filename:join(Dir,"usm.old"), + filename:join(Dir,"usm.conf")). + + +update_community([v3], _Dir) -> + ok; +update_community(_, Dir) -> + Conf = [{"no-rights", "no-rights", "no-rights", "", ""}], + ?line ok = snmp_config:update_agent_community_config(Dir, Conf). + + +-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]). +update_vacm(_Vsn, Dir) -> + Conf = [{vacmSecurityToGroup, usm, "authMD5", "initial"}, + {vacmSecurityToGroup, usm, "authSHA", "initial"}, + {vacmSecurityToGroup, usm, "privDES", "initial"}, + {vacmSecurityToGroup, usm, "newUser", "initial"}, + {vacmViewTreeFamily, "internet", ?tDescr_instance, + excluded, null}], + ?line ok = snmp_config:update_agent_vacm_config(Dir, Conf). + + +write_community_conf(Dir, Conf) -> + snmp_config:write_agent_community_config(Dir, "", Conf). + +write_target_addr_conf(Dir, Conf) -> + snmp_config:write_agent_target_addr_config(Dir, "", Conf). + +write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> + snmp_config:write_agent_snmp_target_addr_conf(Dir, ManagerIp, UDP, Vsns). + +rewrite_target_addr_conf(Dir, NewPort) -> + ?DBG("rewrite_target_addr_conf -> entry with" + "~n NewPort: ~p", [NewPort]), + TAFile = filename:join(Dir, "target_addr.conf"), + case file:read_file_info(TAFile) of + {ok, _} -> ok; + {error, R} -> ?ERR("failure reading file info of " + "target address config file: ~p",[R]), + ok + end, + + ?line [TrapAddr|Addrs] = + snmp_conf:read(TAFile, + fun(R) -> rewrite_target_addr_conf_check(R) end), + + ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]), + + NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs], + + ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]), + + ?line ok = file:rename(filename:join(Dir,"target_addr.conf"), + filename:join(Dir,"target_addr.old")), + + ?line ok = snmp_config:write_agent_target_addr_config(Dir, "", NewAddrs). + +rewrite_target_addr_conf_check(O) -> + {ok,O}. + +rewrite_target_addr_conf2(NewPort,{Name,Ip,_Port,Timeout,Retry, + "std_trap",EngineId}) -> + ?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]), + {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; +rewrite_target_addr_conf2(_NewPort,O) -> + ?LOG("rewrite_target_addr_conf2 -> entry with " + "~n O: ~p",[O]), + O. + +reset_target_addr_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_addr.old"), + filename:join(Dir,"target_addr.conf")). + +write_target_params_conf(Dir, Vsns) -> + F = fun(v1) -> {"target_v1", v1, v1, "all-rights", noAuthNoPriv}; + (v2) -> {"target_v2", v2c, v2c, "all-rights", noAuthNoPriv}; + (v3) -> {"target_v3", v3, usm, "all-rights", noAuthNoPriv} + end, + Conf = [F(Vsn) || Vsn <- Vsns], + snmp_config:write_agent_target_params_config(Dir, "", Conf). + +rewrite_target_params_conf(Dir, SecName, SecLevel) + when is_list(SecName) andalso is_atom(SecLevel) -> + ?line ok = file:rename(filename:join(Dir,"target_params.conf"), + filename:join(Dir,"target_params.old")), + Conf = [{"target_v3", v3, usm, SecName, SecLevel}], + snmp_config:write_agent_target_params_config(Dir, "", Conf). + +reset_target_params_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_params.old"), + filename:join(Dir,"target_params.conf")). + +write_notify_conf(Dir) -> + Conf = [{"standard trap", "std_trap", trap}, + {"standard inform", "std_inform", inform}], + snmp_config:write_agent_notify_config(Dir, "", Conf). + +write_view_conf(Dir) -> + Conf = [{2, [1,3,6], included, null}, + {2, ?tDescr_instance, excluded, null}], + snmp_config:write_agent_view_config(Dir, "", Conf). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +copy_file(From, To) -> + {ok, Bin} = file:read_file(From), + ok = file:write_file(To, Bin). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +display_memory_usage() -> + Info = snmpa:info(snmp_master_agent), + TreeSize = key1search(tree_size_bytes, Info), + ProcMem = key1search(process_memory, Info), + MibDbSize = key1search([db_memory,mib], Info), + NodeDbSize = key1search([db_memory,node], Info), + TreeDbSize = key1search([db_memory,tree], Info), + ?INF("Memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p", + [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]). + +key1search([], Res) -> + Res; +key1search([Key|Keys], List) when is_atom(Key) andalso is_list(List) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + key1search(Keys, Val); + false -> + undefined + end; +key1search(Key, List) when is_atom(Key) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + Val; + false -> + undefined + end. + + +regs() -> + lists:sort(registered()). + + +rpc(Node, F, A) -> + rpc:call(Node, snmpa, F, A). + + +%% await_pdu(To) -> +%% await_response(To, pdu). +%% +%% await_trap(To) -> +%% await_response(To, trap). +%% +%% await_any(To) -> +%% await_response(To, any). +%% +%% +%% await_response(To, What) -> +%% await_response(To, What, []). +%% +%% await_response(To, What, Stuff) when is_integer(To) andalso (To >= 0) -> +%% T = t(), +%% receive +%% {snmp_pdu, PDU} when is_record(Trap, pdu) andalso (What =:= pdu) -> +%% {ok, PDU}; +%% {snmp_pdu, Trap} is_when record(Trap, trappdu) andalso (What =:= trap) -> +%% {ok, Trap}; +%% Any when What =:= any -> +%% {ok, Any}; +%% Any -> +%% %% Recalc time +%% NewTo = To - (t() - T) +%% await_reponse(NewTo, What, [{NewTo, Any}|Stuff]) +%% after To -> +%% {error, {timeout, Stuff}} +%% end; +%% await_response(_, Stuff) -> +%% {error, {timeout, Stuff}}. +%% +%% +%% t() -> +%% {A,B,C} = erlang:now(), +%% A*1000000000+B*1000+(C div 1000). +%% +%% +%% timeout() -> +%% timeout(os:type()). +%% +%% timeout(vxworks) -> 7000; +%% timeout(_) -> 3500. + + +%% Time in milli seconds +t() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). diff --git a/lib/snmp/test/snmp_agent_v1_test.erl b/lib/snmp/test/snmp_agent_v1_test.erl new file mode 100644 index 0000000000..52ac6cf58f --- /dev/null +++ b/lib/snmp/test/snmp_agent_v1_test.erl @@ -0,0 +1,2673 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_agent_v1_test). + +%% TODO +%% * Test fault-tolerance (kill master etc) +%% + +-export([]). + +-define(application, snmp). + +-include_lib("kernel/include/file.hrl"). +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). + + +-define(klas1, [1,3,6,1,2,1,7]). +-define(klas2, [1,3,6,1,2,1,9]). +-define(klas3, [1,3,6,1,2,1,8,1]). +-define(klas4, [1,3,6,1,2,1,8,4]). +-define(sa, [1,3,6,1,4,1,193,2]). +-define(system, [1,3,6,1,2,1,1]). +-define(snmp, [1,3,6,1,2,1,11]). +-define(snmpTraps, [1,3,6,1,6,3,1,1,5]). +-define(ericsson, [1,3,6,1,4,1,193]). +-define(testTrap, [1,3,6,1,2,1,15,0]). +-define(xDescr, [1,3,6,1,2,1,17,1]). +-define(xDescr2, [1,3,6,1,2,1,17,2]). + +-define(active, 1). +-define(notInService, 2). +-define(notReady, 3). +-define(createAndGo, 4). +-define(createAndWait, 5). +-define(destroy, 6). + +-define(TRAP_UDP, 5000). + +-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"). + + +%% -- test manager defines -- +-define(MGR, snmp_test_mgr). +-define(GN(X), ?MGR:gn(X)). +-define(G(X), ?MGR:g(X)). +-define(S(X), ?MGR:s(X)). +-define(GB(X), ?MGR:gb(X)). +-define(SEND_BYTES(X), ?MGR:send_bytes(X)). + +%% -- agent test lib defines -- +-define(LIB, snmp_agent_test_lib). +-define(INIT_CASE(X), ?LIB:init_case(X)). +-define(TRY_TEST1(A), ?LIB:try_test(A)). +-define(TRY_TEST2(A, B), ?LIB:try_test(A, B)). +-define(TRY_TEST3(A, B, C), ?LIB:try_test(A, B, C)). +-define(START_SA(A, B, C), ?LIB:start_subagent(A, B, C)). +-define(STOP_SA(A), ?LIB:stop_subagent(A)). +-define(P1(C), ?LIB:p(C)). +-define(P2(F), ?LIB:p(F,[])). +-define(P3(F,A), ?LIB:p(F,A)). +-define(RPC(N, F, A), ?LIB:rpc(N, F, A)). + + +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + +-define(v1_2_3(V1,V2,V3), + case get(vsn) of + v1 -> V1; + v2 -> V2; + _ -> V3 + end). + +all(suite) -> {req, + [mnesia, distribution, + {local_slave_nodes, 2}, {time, 360}], + [{conf, init, cases(), finish}]}. + +init_per_testcase(_Case, Config) when list(Config) -> + Dog = ?t:timetrap(?t:minutes(6)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + Config. + +cases() -> + [simple, + db_notify_client, + processing, + big, + big2, + %% implied, + loop_mib, + api, + subagent, + mnesia, + multiple_reqs, + sa_register, + v1_trap, + sa_error, + next_across_sa, + undo, + standard_mibs, + sparse_table, + cnt_64, + opaque, + %% opaque]. + + change_target_addr_config, + + reported_bugs, + tickets + ]. + + +init(Config) -> + init_all(Config), + init_v1(Config). + +finish(Config) -> + finish_v1(Config), + finish_all(Config). + +init_v1(Config) when list(Config) -> + ?line SaNode = ?config(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v1} | start_v1_agent(Config)]. + +finish_v1(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + + +%%----------------------------------------------------------------- +%% This function takes care of the old OTP-SNMPEA-MIB. +%% Unfortunately, the testcases were written to use the data in the +%% internal tables, and these table are now obsolete and not used +%% by the agent. Therefore, we emulate them by using +%% OLD-SNMPEA-MIB, which uses the default impl. of all tables. +%% +%% These two rows must exist in intCommunityTable +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. +%% (But with the manager's IP address) +%% +%%----------------------------------------------------------------- +init_old() -> + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [6 | "public"], + {get(mip), "public", 2, 2}), + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [13 | "standard trap"], + {get(mip), "standard trap", 2, 1}), + snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]). + + +%% ========================================================================= +%% +%% C A S E S +%% +%% ========================================================================= + +%% -- simple -- + +simple(suite) -> []; +simple(Config) when list(Config) -> + ?P1(simple), + ?INIT_CASE(Config), + + ?TRY_TEST1(simple_standard_test). + +simple_standard_test() -> + ?DBG("simple_standard_test -> entry",[]), + ?GN([[1,1]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]), + + ?GN([[1,3]]), + ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]), + + ?GN([[1,3,6]]), + ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]), + + ?GN([[1,3,6,1]]), + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]), + + ?GN([[1,3,6,1,2]]), + ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]), + + ?GN([[1,3,6,1,2,1]]), + ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]), + + ?GN([[1,3,6,1,2,1,1]]), + ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]), + + ?GN([[sysDescr]]), + ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]), + + ?G([[sysDescr,0]]), + ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]), + + ?G([[sysDescr]]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{[sysDescr], noSuchObject}])), + + ?G([[1,6,7,0]]), + ?line ?v1_2(expect(41, noSuchName, 1, any), + expect(3, [{[1,6,7,0], noSuchObject}])), + + ?GN([[1,13]]), + ?line ?v1_2(expect(4, noSuchName,1, any), + expect(4, [{[1,13], endOfMibView}])), + + ?S([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + + ?G([[sysLocation, 0]]), + ?line expect(6, [{[sysLocation, 0], "new_value"}]), + + io:format("Testing noSuchName and badValue...~n"), + ?S([{[sysServices,0], 3}]), + ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any), + + ?S([{[sysLocation, 0], i, 3}]), + ?line expect(62, ?v1_2(badValue, wrongType), 1, any), + ?DBG("simple_standard_test -> done",[]), + ok. + + +%% -- db_notify_client -- + +%% This is run in the agent node +db_notify_client(suite) -> []; +db_notify_client(Config) when list(Config) -> + ?P1(db_notify_client), + {SaNode, MgrNode, MibDir} = ?INIT_CASE(Config), + ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p", + [SaNode,MgrNode,MibDir]), + snmpa_local_db:register_notify_client(self(),?MODULE), + + %% This call (the manager) will issue to set operations, so + %% we expect to receive to notify(insert) calls. + ?TRY_TEST1(db_notify_client_test), + + ?DBG("await first notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok + end, + + ?DBG("await second notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok + end, + + snmpa_local_db:unregister_notify_client(self()). + + +%% This is run in the manager node +db_notify_client_test() -> + ?DBG("set first new sysLocation",[]), + ?S([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + + ?DBG("set second new sysLocation",[]), + ?S([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]). + +notify(Pid,What) -> + ?DBG("notify(~p,~p) -> called",[Pid,What]), + Pid ! {db_notify_test_reply,What}. + + +%% -- processing -- + +%% Req. Test2 +processing(suite) -> []; +processing(Config) when list(Config) -> + ?P1(processing), + ?INIT_CASE(Config), + + ?line load_master("Test2"), + ?TRY_TEST1(v1_proc), + ?line unload_master("Test2"). + +v1_proc() -> + ?DBG("v1_proc -> entry", []), + %% According to RFC1157. + %% Template: <Section>:<list no> + v1_get_p(), + v1_get_next_p(), + v1_set_p(). + +v1_get_p() -> + %% 4.1.2:1 + ?G([[test2]]), + ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]), + ?G([[tDescr]]), + ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]), + ?G([[tDescr2,0]]), + ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]), + ?G([[tDescr3,0]]), + ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]), + ?G([[tDescr4,0]]), + ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]), + ?G([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'}, + {[tDescr,0], 'NULL'}]), + ?G([[sysDescr,3]]), + ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]), + + %% 4.1.2:2 + ?G([[tTable]]), + ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]), + ?G([[tEntry]]), + ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]), + + %% 4.1.2:3 + ?G([[tTooBig, 0]]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.2:4 + ?G([[tGenErr1, 0]]), + ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + ?G([[tGenErr2, 0]]), + ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + ?G([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]). + +v1_get_next_p() -> + %% 4.1.3:1 + ?GN([[1,3,7,1]]), + ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]), + + ?GN([[tDescr2]]), + ?line expect(11, tooBig, 0, any), + + %% 4.1.3:2 + ?GN([[tTooBig]]), + io:format("We currently don't handle tooBig correct!!!\n"), + %% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]), + ?line expect(20, tooBig, 0, any), + + %% 4.1.3:3 + ?GN([[tGenErr1]]), + %% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]), + ?line expect(40, genErr, 1, any), + + ?GN([[tGenErr2]]), + %% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]), + ?line expect(41, genErr, 1, any), + + ?GN([[sysDescr], [tGenErr3]]), + %% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'}, + %% {[tGenErr3], 'NULL'}]). + ?line expect(42, genErr, 2, any). + +v1_set_p() -> + %% 4.1.5:1 + ?S([{[1,3,7,0], i, 4}]), + ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]), + + ?S([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]), + + ?S([{[tDescr3,0], s, "read-only"}]), + ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]), + + ?S([{[tDescr3], s, "noSuchObject"}]), + ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]), + + ?S([{[tDescr3,1], s, "noSuchInstance"}]), + ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]), + + ?S([{[tDescr2,0], s, "inconsistentName"}]), + ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]), + + %% 4.1.5:2 + ?S([{[tDescr2, 0], i, 4}]), + ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]), + + ?S([{[tDescr2, 0], s, "badValue"}]), + ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.1.5:3 + %% The standard is quite incorrect here. The resp pdu was too big. In + %% the resp pdu, we have the original vbs. In the tooBig pdu we still + %% have to original vbs => the tooBig pdu is too big as well!!! It + %% may not get it to the manager, unless the agent uses 'NULL' instead + %% of the std-like original value. + ?S([{[tTooBig, 0], s, ?tooBigStr}]), + %% according to std: + %% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.5:4 + ?S([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]), + + ?S([{[tDescr2, 0], s, "commit_fail"}]), + ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]). + + +%% -- big -- + +big(suite) -> []; +big(Config) when list(Config) -> + ?P1(big), + {SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = ?START_SA(SaNode, ?klas1, "Klas1"), + ?DBG("big -> SA: ~p", [SA]), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + ?TRY_TEST1(big_test), + + ?line ?STOP_SA(SA), + ?line unload_master("OLD-SNMPEA-MIB"). + +%% Req: system group, OLD-SNMPEA-MIB, Klas1 +big_test() -> + ?DBG("big_test -> testing simple next/get/set @ master agent...",[]), + simple_standard_test(), + + ?DBG("big_test -> testing simple next/get/set @ subagent...",[]), + ?GN([[klas1]]), + ?line expect(1, [{[fname,0], ""}]), + + ?G([[fname,0]]), + ?line expect(2, [{[fname,0], ""}]), + + ?S([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + + ?G([[fname,0]]), + ?line expect(4, [{[fname,0], "test set"}]), + + ?DBG("big_test -> " + "testing next from last instance in master to subagent...",[]), + ?GN([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname,0], "test set"}]), + + ?GN([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname,0], "test set"}]), + ?S([{[fname,0], s, ""}]), + ?line expect(52, [{[fname,0], ""}]), + + table_test(), + + ?DBG("big_test -> adding one row in subagent table",[]), + _FTab = [friendsEntry], + ?S([{[friendsEntry, [2, 3]], s, "kompis3"}, + {[friendsEntry, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + + ?G([[friendsEntry, [2, 3]], + [friendsEntry, [3, 3]]]), + ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?active}]), + + ?S([{[friendsEntry, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]), + + otp_1131(), + + ?DBG("big_test -> adding two rows in subagent table with special INDEX", + []), + ?S([{[kompissEntry, [1, 3]], s, "kompis3"}, + {[kompissEntry, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?createAndGo}]), + + ?G([[kompissEntry, [1, 3]], + [kompissEntry, [2, 3]]]), + ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + + ?GN([[kompissEntry, [1]], + [kompissEntry, [2]]]), + ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + + ?S([{[kompissEntry, [1, 2]], s, "kompis3"}, + {[kompissEntry, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?createAndGo}]), + + ?GN([[kompissEntry, [1, 1]], + [kompissEntry, [2, 1]]]), + ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?active}]), + + ?S([{[kompissEntry, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]), + + ?S([{[kompissEntry, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]), + ?DBG("big_test -> done",[]), + ok. + + +%% Req. system group, Klas2, OLD-SNMPEA-MIB +big_test_2() -> + ?P1(big_test_2), + + ?P2("Testing simple next/get/set @ master agent (2)..."), + simple_standard_test(), + + p("Testing simple next/get/set @ subagent (2)..."), + ?GN([[klas2]]), + ?line expect(1, [{[fname2,0], ""}]), + + ?G([[fname2,0]]), + ?line expect(2, [{[fname2,0], ""}]), + + ?S([{[fname2,0], s, "test set"}]), + ?line expect(3, [{[fname2,0], "test set"}]), + + ?G([[fname2,0]]), + ?line expect(4, [{[fname2,0], "test set"}]), + + otp_1298(), + + ?P2("Testing next from last object in master to subagent (2)..."), + ?GN([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname2,0], "test set"}]), + + ?GN([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname2,0], "test set"}]), + + table_test(), + + ?P2("Adding one row in subagent table (2)"), + ?S([{[friendsEntry2, [2, 3]], s, "kompis3"}, + {[friendsEntry2, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?createAndGo}]), + + ?G([[friendsEntry2, [2, 3]], + [friendsEntry2, [3, 3]]]), + ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?active}]), + + ?S([{[friendsEntry2, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]), + + ?P2("Adding two rows in subagent table with special INDEX (2)"), + ?S([{[kompissEntry2, [1, 3]], s, "kompis3"}, + {[kompissEntry2, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?createAndGo}]), + ?G([[kompissEntry2, [1, 3]], + [kompissEntry2, [2, 3]]]), + ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + ?GN([[kompissEntry2, [1]], + [kompissEntry2, [2]]]), + ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + + ?S([{[kompissEntry2, [1, 2]], s, "kompis3"}, + {[kompissEntry2, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?createAndGo}]), + + ?GN([[kompissEntry2, [1, 1]], + [kompissEntry2, [2, 1]]]), + ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?active}]), + + ?S([{[kompissEntry2, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]), + + ?S([{[kompissEntry2, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]), + ok. + + +%% -- bug2 -- + +big2(suite) -> []; +big2(Config) when list(Config) -> + ?P1(big2), + %% This is exactly the same tests as 'big', but with the + %% v2 equivalent of the mibs. + {SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config), + + ?P2("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = ?START_SA(SaNode, ?klas1, "Klas1-v2"), + ?line load_master("OLD-SNMPEA-MIB-v2"), + ?line init_old(), + + ?TRY_TEST1(big_test), + + ?line ?STOP_SUBAGENT(SA), + ?line unload_master("OLD-SNMPEA-MIB-v2"). + + +implied(suite) -> []; +implied(Config) when list(Config) -> + ?P1(implied), + ?INIT_CASE(Config), + + ?line load_master("Test1"), + + ?TRY_TEST2(implied_test,[whereis(snmp_master_agent)]), + + ?line unload_master("Test1"). + +%% Req. Test1 +implied_test(MA) -> + ?LOG("implied_test -> start",[]), + + snmpa:verbosity(MA,trace), + snmpa:verbosity(MA,trace), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = "apa", + Idx2 = "qq", + + ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]), + ?S([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]), + ?line expect(1, [{[testStatus, Idx1], ?createAndGo}, + {[testDescr, Idx1], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]), + + ?S([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]), + ?line expect(2, [{[testStatus, Idx2], ?createAndGo}, + {[testDescr, Idx2], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr)",[]), + + ?GN([[testDescr]]), + ?line expect(3, [{[testDescr,Idx1], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr) of row 1",[]), + + ?GN([[testDescr,Idx1]]), + ?line expect(4, [{[testDescr,Idx2], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]), + ?S([{[testStatus, Idx1], i, ?destroy}]), + ?line expect(5, [{[testStatus, Idx1], ?destroy}]), + + ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]), + ?S([{[testStatus, Idx2], i, ?destroy}]), + ?line expect(6, [{[testStatus, Idx2], ?destroy}]), + + %% Try the same in other table + Idx3 = [1, "apa"], + Idx4 = [1, "qq"], + ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]), + ?S([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]), + ?line expect(1, [{[testStatus2, Idx3], ?createAndGo}, + {[testDescr2, Idx3], "row 1"}]), + + ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]), + ?S([{[testStatus2, Idx4], i, ?createAndGo}, + {[testDescr2,Idx4],s,"row 2"}]), + ?line expect(2, [{[testStatus2, Idx4], ?createAndGo}, + {[testDescr2, Idx4], "row 2"}]), + + ?DBG("implied_test -> get-next(testDescr2)",[]), + ?GN([[testDescr2]]), + ?line expect(3, [{[testDescr2,Idx3], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr2) of row 1",[]), + + ?GN([[testDescr2,Idx3]]), + ?line expect(4, [{[testDescr2,Idx4], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]), + ?S([{[testStatus2, Idx3], i, ?destroy}]), + ?line expect(5, [{[testStatus2, Idx3], ?destroy}]), + + ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]), + ?S([{[testStatus2, Idx4], i, ?destroy}]), + ?line expect(6, [{[testStatus2, Idx4], ?destroy}]), + + snmpa:verbosity(MA,log), + + ?LOG("implied_test -> done",[]). + + +%% -- loop_mib -- + +%%----------------------------------------------------------------- +%% Loop through entire MIB, to make sure that all instrum. funcs +%% works. +%% Load all std mibs that are not loaded by default. +%%----------------------------------------------------------------- +loop_mib(suite) -> []; +loop_mib(Config) when list(Config) -> + ?P1(loop_mib), + %% snmpa:verbosity(master_agent,debug), + %% snmpa:verbosity(mib_server,info), + {SaNode, MgrNode, MibDir} = ?INIT_CASE(Config), + ?DBG("loop_mib -> " + "~n SaNode: ~p" + "~n MgrNode: ~p" + "~n MibDir: ~p", [SaNode, MgrNode, MibDir]), + + ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]), + ?line load_master_std("SNMP-MPD-MIB"), + ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?DBG("loop_mib -> try",[]), + + ?TRY_TEST1(loop_mib), + + ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]), + ?line unload_master("SNMP-MPD-MIB"), + ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + %% snmpa:verbosity(master_agent,log), + %% snmpa:verbosity(mib_server,silence), + ?LOG("loop_mib -> done",[]). + +%% Req. As many mibs all possible +loop_mib() -> + ?DBG("loop_mib -> entry",[]), + N = loop_it([1,1], 0), + ?P3("found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + +loop_it(Oid, N) -> + ?DBG("loop_it -> entry with" + "~n Oid: ~p" + "~n N: ~p", [Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it -> " + "~n NOid: ~p" + "~n Value: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_1 -> " + "~n Value2: ~p",[Value2]), + loop_it(NOid, N+1); + + #pdu{type='get-response', error_status=noSuchName, error_index=1, + varbinds=[_]} -> + ?DBG("loop_it -> done",[]), + N; + + #pdu{type = Type, error_status = Err, error_index = Idx, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs}) + + end. + + +%% -- api -- + +api(suite) -> []; +api(Config) when list(Config) -> + ?P1(api), + ?INIY_CASE(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + ?TRY_TEST2(api_test, [node()]), + + ?line unload_master("OLD-SNMPEA-MIB"). + +%% Req. OLD-SNMPEA-MIB +api_test(MaNode) -> + ?line {value, OID} = ?RPC(MaNode, name_to_oid, [intAgentIpAddress]), + ?line {value, intAgentIpAddress} = ?RPC(MaNode, oid_to_name, [OID]), + ?line false = ?RPC(MaNode, name_to_oid, [intAgentIpAddres]), + ?line false = ?RPC(MaNode, oid_to_name, [[1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = ?RPC(MaNode, enum_to_int, [intViewType, excluded]), + ?line {value, excluded} = ?RPC(MaNode, int_to_enum, [intViewType, 2]), + ?line false = ?RPC(MaNode, enum_to_int, [intViewType, exclude]), + ?line false = ?RPC(MaNode, enum_to_int, [intAgentIpAddress, exclude]), + ?line false = ?RPC(MaNode, enum_to_int, [intAgentIpAddre, exclude]), + ?line false = ?RPC(MaNode, int_to_enum, [intViewType, 3]), + ?line false = ?RPC(MaNode, int_to_enum, [intAgentIpAddress, 2]), + ?line false = ?RPC(MaNode, int_to_enum, [intAgentIpAddre, 2]), + ?line {value, active} = ?RPC(MaNode, int_to_enum, ['RowStatus', ?active]), + ?line {value, ?destroy} = + ?RPC(MaNode, enum_to_int, ['RowStatus', destroy]), + ?line false = ?RPC(MaNode, enum_to_int, ['RowStatus', xxxdestroy]), + ?line false = ?RPC(MaNode, enum_to_int, ['xxRowStatus', destroy]), + ?line false = ?RPC(MaNode, int_to_enum, ['RowStatus', 25]), + ?line false = ?RPC(MaNode, int_to_enum, ['xxRowStatus', 1]), + ?line case snmp:date_and_time() of + List when list(List), length(List) == 8 -> ok; + List when list(List), length(List) == 11 -> ok + end. + + +%% -- subagent -- + +subagent(suite) -> []; +subagent(Config) when list(Config) -> + ?P1(subagent), + {SaNode, _MgrNode, MibDir} = ?INIT_CASE(Config), + + ?line {ok, SA} = ?START_SA(SaNode, ?klas1, "Klas1"), + + ?TRY_TEST1(load_test_sa), + + ?P2("Testing unregister subagent [~w]...", [SA]), + MA = whereis(snmp_master_agent), + ?RPC(SaNode, unregister_subagent, [MA, SA]), + ?TRY_TEST1(unreg_test), + + ?P2("Loading previous subagent mib in master and testing..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]), + ?TRY_TEST1(load_test), + + ?P2("Unloading previous subagent mib in master and testing..."), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]), + + ?TRY_TEST1(unreg_test), + + ?P2("Testing register subagent..."), + ?RPC(SaNode, register_subagent, [MA, ?klas1, SA]), + ?TRY_TEST1(load_test_sa), + + ?line ?STOP_SA(SA), + ?TRY_TEST1(unreg_test). + +%% Req. Klas1 +load_test_sa() -> + ?GN([[?v1_2(sysServices,sysORLastChange), 0]]), + ?line expect(1, [{[fname,0], any}]). + +unreg_test() -> + ?GN([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[snmpInPkts, 0], any}]). + +load_test() -> + ?GN([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[fname,0], ""}]). + + +%% -- mnesia -- + +mnesia(suite) -> []; +mnesia(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent with mnesia impl..."), + {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + ?TRY_TEST1(big_test_2), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + ?TRY_TEST1(unreg_test), + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA). + + +%% -- multiple_reqs -- + +multiple_reqs(suite) -> + {req, [], {conf, init_mul, mul_cases(), finish_mul}}. + +mul_cases() -> + [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err]. + +init_mul(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + [{mul_sub, SA} | Config]. + +finish_mul(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + SA = ?config(mul_sub, Config), + + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA), + lists:keydelete(mul_sub, 1, Config). + + +%% -- mul_get -- + +mul_get(suite) -> []; +mul_get(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get..."), + ?TRY_TEST1(do_mul_get). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_get() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0], Key1c4, [fname,0],Key1c3, + [sysName,0]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,0], "test"}]), + g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]), + ?line ?v1_2(expect(2, noSuchName, [1,4], any), + expect(2, [{[1,3,7,1], noSuchObject}, + {Key1c4, 2}, + {[sysDescr,0], "Erlang SNMP agent"}, + {[1,3,7,2], noSuchObject}, + {Key1c3, 2}, + {[sysDescr,0], "Erlang SNMP agent"}])). + + +%% -- mul_get_err -- + +mul_get_err(suite) -> []; +mul_get_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get with error..."), + ?TRY_TEST1(do_mul_get_err). + +%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3. +do_mul_get_err() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]), + ?line ?v1_2(expect(1, noSuchName, 5, any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,2], noSuchInstance}])), + g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname3,0], noSuchObject}, + {Key1c3, 2}, + {[sysName,1], noSuchInstance}])). + + +%% -- mul_next -- + +mul_next(suite) -> []; +mul_next(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + ?TRY_TEST1(do_mul_next). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, {[fname,0], "test set"}, + {Key1c3, 2}, {[sysName,0], "test"}]). + + +%% -- mul_next_err -- + +mul_next_err(suite) -> []; +mul_next_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + ?TRY_TEST1(do_mul_next_err). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next_err() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[1,3,6,999], endOfMibView}, + {[fname,0], "test set"}, + {[1,3,90], endOfMibView}, + {Key1c3, 2}, + {[sysName,0], "test"}])). + + +%% -- mul_set -- + +mul_set(suite) -> []; +mul_set(Config) when list(Config) -> + ?P(mul_set), + ?INIT_CASE(Config), + + ?TRY_TEST1(do_mul_set). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set() -> + p("Adding one row in subagent table, and one in master table"), + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [sysLocation,0], + [friendsEntry, [3, 3]]]), + ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"}, + {[sysLocation,0], "new_value"}, + {[friendsEntry, [3, 3]], ?active}]), + g([NewKeyc4]), + ?line expect(3, [{NewKeyc4, 2}]), + s([{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]), + ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]). + + +%% -- mul_set_err -- + +mul_set_err(suite) -> []; +mul_set_err(Config) when list(Config) -> + ?P(mul_set_err), + ?INIT_CASE(Config), + + ?TRY_TEST1(do_mul_set_err). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + p("Adding one row in subagent table, and one in master table"), + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {NewKeyc3, 2}, + {[sysUpTime,0], 45}, % sysUpTime (readOnly) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any), + g([[friendsEntry, [2, 3]]]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])), + g([NewKeyc4]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{NewKeyc4, noSuchInstance}])). + + +%% -- sa_register -- + +sa_register(suite) -> []; +sa_register(Config) when list(Config) -> + ?P1(sa_register), + {SaNode, _MgrNode, MibDir} = ?INIT_CASE(Config), + + ?DBG("sa_register -> start subagent", []), + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + + ?DBG("sa_register -> unregister subagent", []), + ?P2("Testing unregister subagent (2)..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + ?TRY_TEST1(unreg_test), + + ?P2("Loading SA-MIB..."), + ?DBG("sa_register -> unload mibs", []), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + ?DBG("sa_register -> unload mibs", []), + snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]), + ?DBG("sa_register -> register subagent", []), + rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]), + ?TRY_TEST1(sa_mib), + + ?DBG("sa_register -> stop subagent", []), + ?line stop_subagent(SA). + +%% Req. SA-MIB +sa_mib() -> + g([[sa, [2,0]]]), + ?line expect(1, [{[sa, [2,0]], 3}]), + s([{[sa, [1,0]], s, "sa_test"}]), + ?line expect(2, [{[sa, [1,0]], "sa_test"}]). + + +%% -- v1_trap -- + +v1_trap(suite) -> []; +v1_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + ?TRY_TEST2(ma_trap1, [MA]), + ?TRY_TEST2(ma_trap2, [MA]), + ?TRY_TEST2(ma_v2_2_v1_trap, [MA]), + ?TRY_TEST2(ma_v2_2_v1_trap2, [MA]), + + p("Testing trap sending from subagent..."), + ?TRY_TEST2(sa_trap1, [SA]), + ?TRY_TEST2(sa_trap2, [SA]), + ?TRY_TEST2(sa_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +ma_trap1(MA) -> + snmpa:send_trap(MA, testTrap2, "standard trap"), + ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]), + snmpa:send_trap(MA, testTrap1, "standard trap"), + ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]). + +ma_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap2(MA) -> + snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1}, + {ifAdminStatus, [1], 1}, + {ifOperStatus, [1], 2}]), + ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}]). + +sa_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]], + "pelle"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}]). + +ma_v2_trap1(MA) -> + ?DBG("ma_v2_traps -> entry with MA = ~p => " + "send standard trap: testTrapv22",[MA]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]), + snmpa:send_trap(MA, testTrapv21, "standard trap"), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmp ++ [1]}]). + +ma_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}]). + +ma_v1_2_v2_trap(MA) -> + snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmpTraps ++ [3]}, + {[ifIndex, 1], 1}, + {[snmpTrapEnterprise, 0], [1,2,3]}]). + + +ma_v1_2_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}, + {[snmpTrapEnterprise, 0], ?system}]). + + +sa_v1_2_v2_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + +sa_v1_2_v2_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], "pelle"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +sa_v1_2_v2_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 2]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +%% -- sa_error -- + +sa_error(suite) -> []; +sa_error(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing sa bad value (is_set_ok)..."), + ?TRY_TEST1(sa_errs_bad_value), + + p("Testing sa gen err (set)..."), + ?TRY_TEST1(sa_errs_gen_err), + + p("Testing too big..."), + ?TRY_TEST1(sa_too_big), + + ?line unload_master("OLD-SNMPEA-MIB"), + stop_subagent(SA). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_bad_value() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2}, + {[sa, [2,0]], 5}, % badValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, badValue, 2, any), + s([{NewKeyc3, 2}, + {[sa, [2,0]], 6}, % wrongValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, ?v1_2(badValue, wrongValue), 2, any), + g([NewKeyc4]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_gen_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2},{NewKeyc4, 2}, + {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]), + ?line expect(1, genErr, 4, any), +% The row might have been added; we don't know. +% (as a matter of fact we do - it is added, because the agent +% first sets its own vars, and then th SAs. Lets destroy it. + s([{NewKeyc5, ?destroy}]), + ?line expect(2, [{NewKeyc5, ?destroy}]). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_too_big() -> + g([[sa, [4,0]]]), + ?line expect(1, tooBig). + + +%% -- next_across_sa -- + +next_across_sa(suite) -> []; +next_across_sa(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Loading another subagent mib..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]), + + rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]), + ?TRY_TEST1(load_test_sa), + + p("Testing next across subagent (endOfMibView from SA)..."), + ?TRY_TEST1(next_across_sa), + + p("Unloading mib"), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + ?TRY_TEST1(unreg_test), + + p("Starting another subagent"), + ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"), + p("Testing next across subagent (wrong prefix from SA)..."), + ?TRY_TEST1(next_across_sa), + + stop_subagent(SA), + stop_subagent(SA2). + +%% Req. Klas1, system group, snmp group (v1/v2) +next_across_sa() -> + gn([[sysDescr],[klas1,5]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {[snmpInPkts, 0], any}]). + + +%% -- undo -- + +undo(suite) -> []; +undo(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing undo phase at master agent..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]), + ?TRY_TEST1(undo_test), + ?TRY_TEST1(api_test2), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]), + + p("Testing bad return values from instrum. funcs..."), + ?TRY_TEST1(bad_return), + + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]), + + p("Testing undo phase at subagent..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]), + ?line ok = snmpa:register_subagent(MA, ?klas3, SA), + ?line ok = snmpa:register_subagent(MA, ?klas4, SA), + ?TRY_TEST1(undo_test), + ?TRY_TEST1(api_test3), + + p("Testing undo phase across master/subagents..."), + ?TRY_TEST1(undo_test), + ?TRY_TEST1(api_test3), + stop_subagent(SA). + +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2} +%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2} +%% Req. Klas3, Klas4 +undo_test() -> + s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]), + ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any), + s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]), + ?line expect(3, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]), + ?line expect(4, ?v1_2(genErr, commitFailed), 1, any), + %% unfortunatly we don't know if we'll get undoFailed or commitFailed. + %% it depends on which order the agent traverses the varbind list. + %% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]), + %% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]), + ?line expect(6, genErr, 2, any). + +%% Req. Klas3, Klas4 +bad_return() -> + g([[fStatus4,4], + [fName4,4]]), + ?line expect(4, genErr, 2, any), + g([[fStatus4,5], + [fName4,5]]), + ?line expect(5, genErr, 1, any), + g([[fStatus4,6], + [fName4,6]]), + ?line expect(6, genErr, 2, any), + gn([[fStatus4,7], + [fName4,7]]), + ?line expect(7, genErr, 2, any), + gn([[fStatus4,8], + [fName4,8]]), + ?line expect(8, genErr, 1, any), + gn([[fStatus4,9], + [fName4,9]]), + ?line expect(9, genErr, 2, any). + + +%% -- standard_mibs -- + +%%%----------------------------------------------------------------- +%%% Test the implementation of standard mibs. +%%% We should *at least* try to GET all variables, just to make +%%% sure the instrumentation functions work. +%%% Note that many of the functions in the standard mib is +%%% already tested by the normal tests. +%%%----------------------------------------------------------------- +standard_mibs(suite) -> + [snmp_standard_mib, + snmp_community_mib, + snmp_framework_mib, + snmp_target_mib, + snmp_notification_mib, + snmp_view_based_acm_mib]. + + +%% -- snmp_standard_mib -- + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v1. +%% o Test the counters and control objects in SNMP-STANDARD-MIB +%%----------------------------------------------------------------- +snmp_standard_mib(suite) -> []; +snmp_standard_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?DBG("snmp_standard_mib -> std_mib_init", []), + ?TRY_TEST1(std_mib_init), + + ?DBG("snmp_standard_mib -> std_mib_a", []), + InBadVsns = ?TRY_TEST1(std_mib_a), + put(vsn, v2), + ?DBG("snmp_standard_mib -> std_mib_read", []), + ?TRY_TEST1(std_mib_read), + put(vsn, v1), + + ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]), + Bad = ?TRY_TEST2(std_mib_b, [InBadVsns]), + ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []), + ?TRY_TEST3(std_mib_read, [], [{community, "bad community"}]), + ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []), + ?TRY_TEST3(std_mib_write, [], [{community, "public"}]), + ?DBG("snmp_standard_mib -> std_mib_asn_err", []), + ?TRY_TEST1(std_mib_asn_err), + ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]), + ?TRY_TEST2(std_mib_c, [Bad]), + ?DBG("snmp_standard_mib -> std_mib_a", []), + ?TRY_TEST1(standard_mib_a), + + ?DBG("snmp_standard_mib -> std_mib_finish", []), + ?TRY_TEST1(std_mib_finish), + ?DBG("snmp_standard_mib -> std_mib_test_finish", []), + ?TRY_TEST3(standard_mib_test_finish, [], [{community, "bad community"}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_a() -> + ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]), + ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]), + ?line OutPkts2 = OutPkts + 1, + %% There are some more counters we could test here, but it's not that + %% important, since they are removed from SNMPv2-MIB. + ok. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_init() -> + %% disable authentication failure traps. (otherwise w'd get many of + %% them - this is also a test to see that it works). + s([{[snmpEnableAuthenTraps,0], 2}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_finish() -> + %% enable again + s([{[snmpEnableAuthenTraps,0], 1}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_test_finish() -> + %% force a authenticationFailure + std_mib_write(), + %% check that we got a trap + ?line expect(2, trap, [1,2,3], 4, 0, []). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_read() -> + ?DBG("std_mib_read -> entry", []), + g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply + ?DBG("std_mib_read -> await timeout (i.e. no reply)", []), + ?line expect(1, timeout). % make sure we don't get a trap! + + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_write() -> + ?DBG("std_mib_write -> entry", []), + s([{[sysLocation, 0], "new_value"}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_asn_err() -> + ?SEND_BYTES([48,99,67,12,0,0,0,0,0,0,5]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_a() -> + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + + ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]), + InBadVsns. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_b(InBadVsns) -> + ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]), + ?line InBadVsns2 = InBadVsns + 1, + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] = + get_req(4, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + {InBadCommunityNames, InBadCommunityUses, InASNErrs}. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) -> + ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] = + get_req(1, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + ?line InBadCommunityNames2 = InBadCommunityNames + 1, + ?line InBadCommunityUses2 = InBadCommunityUses + 1, + ?line InASNErrs2 = InASNErrs + 1. + + +%% -- snmp_community_mib -- + +%%----------------------------------------------------------------- +%% o Bad community uses/name is tested already +%% in SNMPv2-MIB and STANDARD-MIB. +%% o Test add/deletion of rows. +%%----------------------------------------------------------------- +snmp_community_mib(suite) -> []; +snmp_community_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?TRY_TEST1(snmp_community_mib), + ?line unload_master("SNMP-COMMUNITY-MIB"). + +snmp_community_mib_2(X) -> snmp_community_mib(X). + +%% Req. SNMP-COMMUNITY-MIB +snmp_community_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + + +%% -- snmp_framework_mib -- + +%%----------------------------------------------------------------- +%% o Test engine boots / time +%%----------------------------------------------------------------- +snmp_framework_mib(suite) -> []; +snmp_framework_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?TRY_TEST1(snmp_framework_mib), + ?line unload_master("SNMP-FRAMEWORK-MIB"). + +%% Req. SNMP-FRAMEWORK-MIB +snmp_framework_mib() -> + ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]), + ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]), + sleep(5000), + ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]), + if + EngineTime+7 < EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + EngineTime+4 > EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + true -> ok + end, + ?line case get_req(4, [[snmpEngineBoots,0]]) of + [Boots] when integer(Boots) -> ok; + Else -> ?FAIL(Else) + end, + ok. + + +%% -- snmp_target_mib -- + +snmp_target_mib(suite) -> []; +snmp_target_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-TARGET-MIB"), + ?TRY_TEST1(snmp_target_mib), + ?line unload_master("SNMP-TARGET-MIB"). + +snmp_target_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + + +%% -- snmp_notification_mib -- + +snmp_notification_mib(suite) -> []; +snmp_notification_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?TRY_TEST1(snmp_notification_mib), + ?line unload_master("SNMP-NOTIFICATION-MIB"). + +snmp_notification_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + + +%% -- snmp_view_based_acm_mib -- + +%%----------------------------------------------------------------- +%% o add/delete views and try them +%% o try boundaries +%%----------------------------------------------------------------- +snmp_view_based_acm_mib(suite) -> []; +snmp_view_based_acm_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master("Test2"), + snmp_view_based_acm_mib(), + ?line unload_master("Test2"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +snmp_view_based_acm_mib() -> + snmpa:verbosity(net_if,trace), + snmpa:verbosity(master_agent,trace), + ?LOG("start snmp_view_based_acm_mib test",[]), + %% The user "no-rights" is present in USM, and is mapped to security + %% name 'no-rights", which is not present in VACM. + %% So, we'll add rights for it, try them and delete them. + %% We'll give "no-rights" write access to tDescr.0 and read access + %% to tDescr2.0 + %% These are the options we'll use to the mgr + Opts = [{user, "no-rights"}, {community, "no-rights"}], + %% Find the valid secmodel, and one invalid secmodel. + {SecMod, InvSecMod} = + case get(vsn) of + v1 -> {?SEC_V1, ?SEC_V2C}; + v2 -> {?SEC_V2C, ?SEC_USM}; + v3 -> {?SEC_USM, ?SEC_V1} + end, + ?DBG("assign rights for 'no-rights'",[]), + ?line ?TRY_TEST3(use_no_rights, [], Opts), + + %% Now, add a mapping from "no-rights" -> "no-rights-group" + GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]], + GRow1 = + [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"}, + {GRow1Status, ?createAndGo}], + ?DBG("set '~p'",[GRow1]), + ?line ?TRY_TEST2(do_set, [GRow1]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line ?TRY_TEST3(use_no_rights, [], Opts), + + %% Create a mapping for another sec model, and make sure it dosn't + %% give us access + GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]], + GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"}, + {GRow2Status, ?createAndGo}], + + ?DBG("set '~p'",[GRow2]), + ?line ?TRY_TEST2(do_set, [GRow2]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line ?TRY_TEST3(use_no_rights, [], Opts), + + %% Delete that row + ?line ?TRY_TEST2(del_row, [GRow2Status]), + + RVName = "rv_name", + WVName = "wv_name", + + %% Access row + ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1], + ARow1Status = [vacmAccessStatus, ARow1Idx], + ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1}, + {[vacmAccessReadViewName, ARow1Idx], RVName}, + {[vacmAccessWriteViewName, ARow1Idx], WVName}, + {ARow1Status, ?createAndGo}], + + %% This access row would give acces, if InvSecMod was valid. + ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1], + ARow2Status = [vacmAccessStatus, ARow2Idx], + ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1}, + {[vacmAccessReadViewName, ARow2Idx], "internet"}, + {[vacmAccessWriteViewName, ARow2Idx], "internet"}, + {ARow2Status, ?createAndGo}], + + ?line ?TRY_TEST2(do_set, [ARow2]), + + ?line ?TRY_TEST3(use_no_rights, [], Opts), + + %% Delete that row + ?line ?TRY_TEST2(del_row, [ARow2Status]), + + + %% Add valid row + ?line ?TRY_TEST2(do_set, [ARow1]), + + ?line ?TRY_TEST3(use_no_rights, [], Opts), + + %% Create the view family + VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access + VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access + VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access + VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access + VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx], + VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx], + VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx], + VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx], + + ?line ?TRY_TEST2(add_row, [VRow1Status]), + ?line ?TRY_TEST2(add_row, [VRow2Status]), + ?line ?TRY_TEST2(add_row, [VRow3Status]), + + %% We're supposed to have access now... + ?line ?TRY_TEST3(use_rights, [], Opts), + + %% Change Row3 to Row4 + ?line ?TRY_TEST2(del_row, [VRow3Status]), + ?line ?TRY_TEST2(add_row, [VRow4Status]), + + %% We should still have access... + ?line ?TRY_TEST3(use_rights, [], Opts), + + %% Delete rows + ?line ?TRY_TEST2(del_row, [GRow1Status]), + + ?line ?TRY_TEST3(use_no_rights, [], Opts), + + %% Delete rest of rows + ?line ?TRY_TEST2(del_row, [ARow1Status]), + ?line ?TRY_TEST2(del_row, [VRow1Status]), + ?line ?TRY_TEST2(del_row, [VRow2Status]), + ?line ?TRY_TEST2(del_row, [VRow4Status]), + + ?line ?TRY_TEST3(use_no_rights, [], Opts), + snmpa:verbosity(master_agent,log). + +do_set(Row) -> + s(Row), + expect(1, Row). + +add_row(RowStatus) -> + s([{RowStatus, ?createAndGo}]), + expect(1, [{RowStatus, ?createAndGo}]). + +del_row(RowStatus) -> + s([{RowStatus, ?destroy}]), + expect(1, [{RowStatus, ?destroy}]). + + + +use_no_rights() -> + g([[xDescr,0]]), + ?v1_2_3(expect(11, noSuchName, 1, any), + expect(12, [{[xDescr,0], noSuchObject}]), + expect(13, authorizationError, 1, any)), + g([[xDescr2,0]]), + ?v1_2_3(expect(21, noSuchName, 1, any), + expect(22, [{[xDescr2,0], noSuchObject}]), + expect(23, authorizationError, 1, any)), + gn([[xDescr]]), + ?v1_2_3(expect(31, noSuchName, 1, any), + expect(32, [{[xDescr], endOfMibView}]), + expect(33, authorizationError, 1, any)), + s([{[xDescr,0], "tryit"}]), + ?v1_2_3(expect(41, noSuchName, 1, any), + expect(42, noAccess, 1, any), + expect(43, authorizationError, 1, any)). + + +use_rights() -> + g([[xDescr,0]]), + expect(1, [{[xDescr,0], any}]), + g([[xDescr2,0]]), + expect(2, [{[xDescr2,0], any}]), + s([{[xDescr,0], "tryit"}]), + expect(3, noError, 0, any), + g([[xDescr,0]]), + expect(4, [{[xDescr,0], "tryit"}]). + + +%% -- sparse_table -- + +sparse_table(suite) -> []; +sparse_table(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config), + + ?line load_master("Test1"), + ?TRY_TEST1(sparse_table_test), + ?line unload_master("Test1"). + +%% Req. Test1 +sparse_table_test() -> + p("Testing sparse table..."), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + s([{[sparseStatus, Idx1], i, ?createAndGo}, + {[sparseDescr, Idx1], s, "row 1"}]), + ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo}, + {[sparseDescr, Idx1], "row 1"}]), + s([{[sparseStatus, Idx2], i, ?createAndGo}, + {[sparseDescr, Idx2], s, "row 2"}]), + ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo}, + {[sparseDescr, Idx2], "row 2"}]), + ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2], + [sparseStatus,Idx1], [sparseStatus,Idx2]]), + gb(0,5,[[sparseIndex]])), + ?line expect(3, [{[sparseDescr,Idx1], "row 1"}, + {[sparseDescr,Idx2], "row 2"}, + {[sparseStatus,Idx1], ?active}, + {[sparseStatus,Idx2], ?active}, + {[sparseStr,0], "slut"}]), + % Delete the rows + s([{[sparseStatus, Idx1], i, ?destroy}]), + ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]), + s([{[sparseStatus, Idx2], i, ?destroy}]), + ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]). + + +%% -- cnt_64 -- + +cnt_64(suite) -> []; +cnt_64(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + ?TRY_TEST2(cnt_64_test, [MA]), + ?line unload_master("Test1"). + +%% Req. Test1 +cnt_64_test(MA) -> + ?LOG("start cnt64 test (~p)",[MA]), + snmpa:verbosity(MA,trace), + ?LOG("start cnt64 test",[]), + p("Testing Counter64, and at the same time, RowStatus is not last column"), + + ?DBG("get cnt64",[]), + g([[cnt64,0]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(1, noSuchName, 1, any), + expect(1, [{[cnt64,0],18446744073709551615}])), + ?DBG("get-next cnt64",[]), + gn([[cnt64]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]), + expect(2, [{[cnt64,0],18446744073709551615}])), + ?DBG("send cntTrap",[]), + snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"}, + {cnt64, 10}, + {sysLocation, "here"}]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"}, + {[sysLocation,0], "here"}]), + expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [1]}, + {[sysContact,0], "pelle"}, + {[cnt64,0], 10}, + {[sysLocation,0], "here"}])), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + ?DBG("create row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]), + ?DBG("create row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]), + + ?DBG("get-next (cntIndex)",[]), + gn([[cntIndex]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]), + expect(3, [{[cntCnt,Idx1], 0}])), + % Delete the rows + ?DBG("delete row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(4, [{[cntStatus, Idx1], ?destroy}]), + ?DBG("delete row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(5, [{[cntStatus, Idx2], ?destroy}]), + catch snmpa:verbosity(MA,log), + ?DBG("done",[]), + ok. + + +%% -- opaque -- + +opaque(suite) -> []; +opaque(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config), + + ?line load_master("Test1"), + ?TRY_TEST1(opaque_test), + ?line unload_master("Test1"). + +%% Req. Test1 +opaque_test() -> + p("Testing Opaque datatype..."), + g([[opaqueObj,0]]), + ?line expect(1, [{[opaqueObj,0], "opaque-data"}]). + + +%% -- change_target_addr_config -- + +change_target_addr_config(suite) -> []; +change_target_addr_config(Config) when list(Config) -> + p("Testing changing target address config..."), + ?LOG("change_target_addr_config -> entry",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(sname,snmp_suite), + put(verbosity,trace), + + MA = whereis(snmp_master_agent), + + ?LOG("change_target_addr_config -> load TestTrap",[]), + ?line load_master("TestTrap"), + + ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,trace), + + %% First send some traps that will arive att the original manager + ?LOG("change_target_addr_config -> send trap",[]), + ?TRY_TEST2(ma_trap1, [MA]), + + ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,silence), + + %% Start new dummy listener + ?LOG("change_target_addr_config -> start dummy manager",[]), + ?line {ok,Pid,NewPort} = dummy_manager_start(MA), + + %% Reconfigure + ?LOG("change_target_addr_config -> reconfigure",[]), + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_addr_conf(AgentDir, NewPort), + ?line snmp_target_mib:reconfigure(AgentDir), + + %% Send the trap again + ?LOG("change_target_addr_config -> send trap again",[]), + catch dummy_manager_send_trap2(Pid), + + ?LOG("change_target_addr_config -> await trap ack",[]), + catch dummy_manager_await_trap2_ack(), + + ?LOG("change_target_addr_config -> stop dummy manager",[]), + ?line ok = dummy_manager_stop(Pid), + + ?LOG("change_target_addr_config -> reset target address config",[]), + ?line reset_target_addr_conf(AgentDir), + + ?LOG("change_target_addr_config -> unload TestTrap",[]), + ?line unload_master("TestTrap"). + + +dummy_manager_start(MA) -> + ?DBG("dummy_manager_start -> entry",[]), + Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]), + ?DBG("dummy_manager_start -> Pid: ~p",[Pid]), + await_dummy_manager_started(Pid). + +await_dummy_manager_started(Pid) -> + receive + {dummy_manager_started,Pid,Port} -> + ?DBG("dummy_manager_start -> acknowledge received with" + "~n Port: ~p",[Port]), + {ok,Pid,Port}; + {'EXIT', Pid, Reason} -> + {error, Pid, Reason}; + O -> + ?LOG("dummy_manager_start -> received unknown message:" + "~n ~p",[O]), + await_dummy_manager_started(Pid) + end. + +dummy_manager_stop(Pid) -> + ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]), + Pid ! stop, + receive + {dummy_manager_stopping, Pid} -> + ?DBG("dummy_manager_stop -> acknowledge received",[]), + ok + after 10000 -> + ?ERR("dummy_manager_stop -> timeout",[]), + timeout + end. + +dummy_manager_send_trap2(Pid) -> + ?DBG("dummy_manager_send_trap2 -> entry",[]), + Pid ! {send_trap,testTrap2}. + +dummy_manager_await_trap2_ack() -> + ?DBG("dummy_manager_await_trap2 -> entry",[]), + receive + {received_trap,Trap} -> + ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]), + %% Note: + %% Without this sleep the v2_inform_i testcase failes! There + %% is no relation between these two test cases as far as I + %% able to figure out... + sleep(60000), + ok; + O -> + ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]), + ok + after 10000 -> + ?ERR("dummy_manager_await_trap2 -> timeout",[]), + timeout + end. + +dummy_manager_init(Parent,MA) -> + ?DBG("dummy_manager_init -> entry with" + "~n Parent: ~p" + "~n MA: ~p",[Parent,MA]), + {ok,S} = gen_udp:open(0,[{recbuf,65535}]), + ?DBG("dummy_manager_init -> S: ~p",[S]), + {ok,Port} = inet:port(S), + ?DBG("dummy_manager_init -> Port: ~p",[Port]), + Parent ! {dummy_manager_started,self(),Port}, + dummy_manager_loop(Parent,S,MA). + +dummy_manager_loop(P,S,MA) -> + ?LOG("dummy_manager_loop -> ready for receive",[]), + receive + {send_trap,Trap} -> + ?LOG("dummy_manager_loop -> received trap send request" + "~n Trap: ~p",[Trap]), + snmpa:send_trap(MA, Trap, "standard trap"), + dummy_manager_loop(P,S,MA); + {udp, _UdpId, Ip, UdpPort, Bytes} -> + ?LOG("dummy_manager_loop -> received upd message" + "~n from: ~p:~p" + "~n size: ~p", + [Ip, UdpPort, dummy_manager_message_sz(Bytes)]), + R = dummy_manager_handle_message(Bytes), + ?DBG("dummy_manager_loop -> R: ~p",[R]), + P ! R, + dummy_manager_loop(P,S,MA); + stop -> + ?DBG("dummy_manager_loop -> received stop request",[]), + P ! {dummy_manager_stopping, self()}, + gen_udp:close(S), + exit(normal); + O -> + ?LOG("dummy_manager_loop -> received unknown message:" + "~n ~p",[O]), + dummy_manager_loop(P,S,MA) + end. + +dummy_manager_message_sz(B) when binary(B) -> + size(B); +dummy_manager_message_sz(L) when list(L) -> + length(L); +dummy_manager_message_sz(_) -> + undefined. + +dummy_manager_handle_message(Bytes) -> + case (catch snmp_pdus:dec_message(Bytes)) of + {'EXIT',Reason} -> + ?ERR("dummy_manager_handle_message -> " + "failed decoding message only:~n ~p",[Reason]), + {error,Reason}; + M -> + ?DBG("dummy_manager_handle_message -> decoded message:" + "~n ~p",[M]), + {received_trap,M} + end. + + +%% -- reported_bugs -- + +%%%----------------------------------------------------------------- +%%% Testing of reported bugs and other tickets. +%%%----------------------------------------------------------------- + +reported_bugs(suite) -> + [otp_1128, otp_1129, otp_1131, otp_1162, + otp_1222, otp_1298, otp_1331, otp_1338, + otp_1342, otp_2776, otp_2979, otp_3187, otp_3725]. + +%%----------------------------------------------------------------- +%% Ticket: OTP-1128 +%% Slogan: Bug in handling of createAndWait set-requests. +%%----------------------------------------------------------------- +otp_1128(suite) -> []; +otp_1128(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?TRY_TEST1(otp_1128), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1128() -> + io:format("Testing bug reported in ticket OTP-1128...~n"), + + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + + s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(29, [{NewKeyc5, ?notReady}]), + s([{NewKeyc5, ?active}, {NewKeyc3, 2}]), + ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(31, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(32, [{NewKeyc5, ?destroy}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1129, OTP-1169 +%% Slogan: snmpa:int_to_enum crashes on bad oids +%%----------------------------------------------------------------- +otp_1129(suite) -> []; +otp_1129(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + ?TRY_TEST2(otp_1129_i, [node()]), + ?line unload_master("Klas3"). + +otp_1129_i(MaNode) -> + io:format("Testing bug reported in ticket OTP-1129...~n"), + false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]), + false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1131 +%% Slogan: Agent crashes / erlang node halts if RowIndex in a +%% setrequest is of bad type, e.g. an INDEX {INTEGER}, +%% and RowIdenx [3,2]. +%%----------------------------------------------------------------- +otp_1131(suite) -> []; +otp_1131(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas1"), + ?TRY_TEST1(otp_1131), + ?line unload_master("Klas1"). + +otp_1131() -> + io:format("Testing bug reported in ticket OTP-1131...~n"), + s([{[friendsEntry, [2, 3, 1]], s, "kompis3"}, + {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1162 +%% Slogan: snmp_agent can't handle wrongValue from instrum.func +%%----------------------------------------------------------------- +otp_1162(suite) -> []; +otp_1162(Config) when list(Config) -> + ?P1(otp_1162), + {SaNode, _MgrNode, _MibDir} = ?INIT_CASE(Config), + ?line {ok, SA} = ?START_SA(SaNode, ?sa, "SA-MIB"), + ?TRY_TEST1(otp_1162), + ?STOP_SA(SA). + +otp_1162() -> + s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok) + ?line expect(1, ?v1_2(badValue, wrongValue), 1, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1222 +%% Slogan: snmp agent crash if faulty index is returned from instrum +%%----------------------------------------------------------------- +otp_1222(suite) -> []; +otp_1222(Config) when list(Config) -> + ?P1(otp_1222), + ?INIT_CASE(Config), + ?line load_master("Klas3"), + ?line load_master("Klas4"), + ?TRY_TEST1(otp_1222), + ?line unload_master("Klas3"), + ?line unload_master("Klas4"). + +otp_1222() -> + io:format("Testing bug reported in ticket OTP-1222...~n"), + s([{[fStatus4,1], 4}, {[fName4,1], 1}]), + ?line expect(1, genErr, 0, any), + s([{[fStatus4,2], 4}, {[fName4,2], 1}]), + ?line expect(2, genErr, 0, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1298 +%% Slogan: Negative INTEGER values are treated as positive. +%%----------------------------------------------------------------- +otp_1298(suite) -> []; +otp_1298(Config) when list(Config) -> + ?P1(otp_1298), + ?INIT_CASE(Config), + ?line load_master("Klas2"), + ?TRY_TEST1(otp_1298), + ?line unload_master("Klas2"). + +otp_1298() -> + io:format("Testing bug reported in ticket OTP-1298...~n"), + s([{[fint,0], -1}]), + ?line expect(1298, [{[fint,0], -1}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1331 +%% Slogan: snmp_generic should return noError when deleting non-ex row +%%----------------------------------------------------------------- +otp_1331(suite) -> []; +otp_1331(Config) when list(Config) -> + ?P1(otp_1331), + ?INIT_CASE(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?TRY_TEST1(otp_1331), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1331() -> + NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")], + s([{NewKeyc5, ?destroy}]), + ?line expect(1, [{NewKeyc5, ?destroy}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1338 +%% Slogan: snmp bug in initialisation of default values for mnesia tabs +%%----------------------------------------------------------------- +otp_1338(suite) -> []; +otp_1338(Config) when list(Config) -> + ?P1(otp_1338), + ?INIT_CASE(Config), + ?line load_master("Klas2"), + ?TRY_TEST1(otp_1338), + ?line unload_master("Klas2"). + +otp_1338() -> + s([{[kStatus2, 7], i, ?createAndGo}]), + ?line expect(1, [{[kStatus2, 7], ?createAndGo}]), + g([[kName2, 7]]), + ?line expect(2, [{[kName2, 7], "JJJ"}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1342 +%% Slogan: default impl of snmp table can't handle bad index access, +%% Set when INDEX is read-write gets into an infinite loop! +%%----------------------------------------------------------------- +otp_1342(suite) -> []; +otp_1342(Config) when list(Config) -> + ?P1(otp_1342), + ?INIT_CASE(Config), + ?line load_master("Klas4"), + ?TRY_TEST1(otp_1342), + ?line unload_master("Klas4"). + +otp_1342() -> + s([{[fIndex5, 1], i, 1}, + {[fName5, 1], i, 3}, + {[fStatus5, 1], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1366 +%% Slogan: snmp traps not sent to all managers +%% Note: NYI! We need a way to tell the test server that we need +%% mgrs on two different machines. +%%----------------------------------------------------------------- +otp_1366(suite) -> []; +otp_1366(Config) when list(Config) -> + ?P1(otp_1366), + ?INIT_CASE(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?TRY_TEST1(otp_1366), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1366() -> + ?INF("NOT YET IMPLEMENTED", []), + 'NYI'. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-2776 +%% Slogan: snmp:validate_date_and_time() fails when time is 00:00 +%%----------------------------------------------------------------- +otp_2776(suite) -> []; +otp_2776(Config) when list(Config) -> + ?P1(otp_2776), + ?INIT_CASE(Config), + ?TRY_TEST1(otp_2776). + +otp_2776() -> + io:format("Testing bug reported in ticket OTP-2776...~n"), + + Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0], + Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00 + Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0], + Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0], + Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0], + Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0], + Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2 + Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0], + Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4 + Dt10_invalid = [], + Dt11_invalid = [kalle,hobbe], + L = [{ 1, true, Dt01_valid}, + { 2, true, Dt02_valid}, + { 3, true, Dt03_valid}, + { 4, false, Dt04_invalid}, + { 5, true, Dt05_valid}, + { 6, true, Dt06_valid}, + { 7, false, Dt07_invalid}, + { 8, true, Dt08_valid}, + { 9, false, Dt09_invalid}, + {10, false, Dt10_invalid}, + {11, false, Dt11_invalid}], + + ?line ok = validate_dat(L). + + +validate_dat(L) -> validate_dat(L,[]). + +validate_dat([],V) -> + Fun = fun({_,X}) -> case X of + ok -> false; + _ -> true + end + end, + validate_dat1( lists:reverse( lists:filter(Fun,V) ) ); +validate_dat([{Id,E,Dat}|T],V) -> + validate_dat(T,[validate_dat2(Id,E,Dat) | V]). + +validate_dat1([]) -> ok; +validate_dat1(L) -> {error,L}. + +validate_dat2(Id, E, Dat) -> + Res = case {E,snmp:validate_date_and_time(Dat)} of + {E,E} -> ok; + {E,A} -> {E,A} + end, + {Id, Res}. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-2979 +%% Slogan: get-next on more than 1 column in an empty table +%% returns bad response. +%%----------------------------------------------------------------- +otp_2979(suite) -> []; +otp_2979(Config) when list(Config) -> + ?P1(otp_2979), + ?INIT_CASE(Config), + ?line load_master("Test1"), + ?line init_old(), + ?TRY_TEST1(otp_2979), + ?line unload_master("Test1"). + +otp_2979() -> + gn([[sparseDescr], [sparseStatus]]), + ?line expect(1, [{[sparseStr,0], "slut"}, + {[sparseStr,0], "slut"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3187 +%% Slogan: get-next on vacmAccessTable for colums > 5 returns +%% endOfTable - should return value. +%%----------------------------------------------------------------- +otp_3187(suite) -> []; +otp_3187(Config) when list(Config) -> + ?P1(otp_3187), + ?INIT_CASE(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + otp_3187(), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +otp_3187() -> + ?line Elements = + snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]), + lists:foreach(fun(E) -> + ?line if E == endOfTable -> + ?FAIL(endOfTable); + true -> ok + end + end, Elements). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-3542 +%% Slogan: +%%----------------------------------------------------------------- +otp_3542(suite) -> []; +otp_3542(Config) when list(Config) -> + ?P1(otp_3542), + ?INIT_CASE(Config), + ?TRY_TEST1(otp_3542). + +otp_3542() -> + io:format("SNMP v3 discovery...~n"), + ?line Res = snmp_test_mgr:d(), + io:format("SNMP v3 discovery result: ~p~n",[Res]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-3725 +%% Slogan: Slow response time on snmpa:int_to_enum +%%----------------------------------------------------------------- +otp_3725(suite) -> []; +otp_3725(Config) when list(Config) -> + ?P1(otp_3725), + ?INIT_CASE(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?TRY_TEST2(otp_3725_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +%% Req. OLD-SNMPEA-MIB +otp_3725_test(MaNode) -> + io:format("Testing feature requested in ticket OTP-3725...~n"), + ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]), + ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]), + ?DBG("otp_3725_test -> Db = ~p",[Db]), + + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [Db, intAgentIpAddress]), + ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name, + [Db,OID]), + ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [Db, [1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [Db, intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum, + [Db, 'RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]), + ok. + + +%% -- tickets -- + +%% These are (ticket) test cases where the initiation has to be done +%% individually. +tickets(suite) -> + [otp_4394]. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-4394 +%% Slogan: Target mib tag list check invalid +%%----------------------------------------------------------------- + +otp_4394(suite) -> {req, [], {conf, + init_otp_4394, + [otp_4394_test], + finish_otp_4394}}. + +init_otp_4394(Config) when list(Config) -> + ?DBG("init_otp_4394 -> entry with" + "~n Config: ~p", [Config]), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line otp_4394_config(AgentDir, MgrDir, Ip), + MasterAgentVerbosity = {master_agent_verbosity, trace}, + NetIfVerbosity = {net_if_verbosity, trace}, + Opts = [MasterAgentVerbosity,NetIfVerbosity], + [{vsn, v1} | start_v1_agent(Config,Opts)]. + +otp_4394_config(AgentDir, MgrDir, Ip0) -> + ?DBG("otp_4394_config -> entry with" + "~n AgentDir: ~p" + "~n MgrDir: ~p" + "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]), + Vsn = [v1], + Ip = tuple_to_list(Ip0), + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip, + ?TRAP_UDP, Ip, 4000, + "OTP-4394 test"), + ?line case update_usm(Vsn, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsn, MgrDir); + false -> + ?line ok + end, + C1 = {"a", "all-rights", "initial", "", "pc"}, + C2 = {"c", "secret", "secret_name", "", "secret_tag"}, + ?line write_community_conf(AgentDir, [C1, C2]), + ?line update_vacm(Vsn, AgentDir), + Ta1 = {"shelob v1", + [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda + "pc1", + "target_v1", "", + %% [255,255,255,255,0,0], + [], + 2048}, + Ta2 = {"bifur v1", + [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip + "pc2", + "target_v1", "", + %% [255,255,255,255,0,0], + [], 2048}, + ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]), + ?line write_target_params_conf(AgentDir, Vsn), + ?line write_notify_conf(AgentDir), + ok. + +finish_otp_4394(Config) when list(Config) -> + ?DBG("finish_otp_4394 -> entry", []), + C1 = stop_agent(Config), + delete_files(C1), + erase(mgr_node), + lists:keydelete(vsn, 1, C1). + +otp_4394_test(suite) -> []; +otp_4394_test(Config) -> + ?P1(otp_4394_test), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?TRY_TEST1(otp_4394_test1), + ?DBG("otp_4394_test -> done", []), + ok. + +otp_4394_test1() -> + ?DBG("otp_4394_test1 -> entry", []), + gn([[1,1]]), + Res = + case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of + %% {error, 1, {"?",[]}, {"~w",[timeout]}} + {error, 1, _, {_, [timeout]}} -> + ?DBG("otp_4394_test1 -> expected result: timeout", []), + ok; + Else -> + Else + end, + ?DBG("otp_4394_test1 -> done with: ~p", [Res]), + Res. + + +mk_ln(X) -> + [length(X) | X]. + + + +%% string used in index +is(S) -> [length(S) | S]. + +expect(A,B) -> ok = ?MGR:expect(A,B). +expect(A,B,C) -> ok = ?MGR:expect(A,B,C). +expect(A,B,C,D) -> ok = ?MGR:expect(A,B,C,D). +expect(A,B,C,D,E,F) -> ok = ?MGR:expect(A,B,C,D,E,F). + diff --git a/lib/snmp/test/snmp_agent_v2_test.erl b/lib/snmp/test/snmp_agent_v2_test.erl new file mode 100644 index 0000000000..eca66dc30d --- /dev/null +++ b/lib/snmp/test/snmp_agent_v2_test.erl @@ -0,0 +1,5657 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_agent_v2_test). + +%% TODO +%% * Test fault-tolerance (kill master etc) +%% + +-compile(export_all). + +-define(application, snmp). + +-include_lib("kernel/include/file.hrl"). +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). +%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl"). + + +-define(klas1, [1,3,6,1,2,1,7]). +-define(klas2, [1,3,6,1,2,1,9]). +-define(klas3, [1,3,6,1,2,1,8,1]). +-define(klas4, [1,3,6,1,2,1,8,4]). +-define(sa, [1,3,6,1,4,1,193,2]). +-define(system, [1,3,6,1,2,1,1]). +-define(snmp, [1,3,6,1,2,1,11]). +-define(snmpTraps, [1,3,6,1,6,3,1,1,5]). +-define(ericsson, [1,3,6,1,4,1,193]). +-define(testTrap, [1,3,6,1,2,1,15,0]). +-define(xDescr, [1,3,6,1,2,1,17,1]). +-define(xDescr2, [1,3,6,1,2,1,17,2]). + +-define(active, 1). +-define(notInService, 2). +-define(notReady, 3). +-define(createAndGo, 4). +-define(createAndWait, 5). +-define(destroy, 6). + +-define(TRAP_UDP, 5000). + +-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"). + +-define(str(X), snmp_pdus:bits_to_str(X)). + +-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n", + [?LINE, self()]), + receive cont -> ok end + end). + + +-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]). +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + +-define(v1_2_3(V1,V2,V3), + case get(vsn) of + v1 -> V1; + v2 -> V2; + _ -> V3 + end). + +all(suite) -> {req, + [mnesia, distribution, + {local_slave_nodes, 2}, {time, 360}], + [{conf, init_all, cases(), finish_all}]}. + +init_per_testcase(_Case, Config) when list(Config) -> + Dog = ?t:timetrap(?t:minutes(6)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + Config. + +cases() -> + case ?OSTYPE() of + vxworks -> + %% No crypto app, so skip v3 testcases + [ + app_info, + test_v1, test_v2, test_v1_v2, + test_multi_threaded, + mib_storage, + tickets]; + _Else -> + [ + app_info, + test_v1, test_v2, test_v1_v2, test_v3, + test_multi_threaded, + mib_storage, + tickets + ] + end. + + +%%%----------------------------------------------------------------- +%%% The test case structure is as follows: +%%% +%%% init_all - starts mnesia, +%%% +%%% init_v1 - starts agent +%%% simple +%%% big - e.g. starts/stops subagent, load/unloads mibs +%%% init_mul +%%% mul_get +%%% mul_set +%%% <etc> +%%% finish_mul +%%% <etc> +%%% finish_v1 +%%% +%%% init_v2 - starts agent +%%% finish_v2 +%%% +%%% init_bilingual - starts agent +%%% finish_bilingual +%%% +%%% finish_all +%%% +%%% There is still one problem with these testsuites. If one test +%%% fails, it may not be possible to run some other cases, as it +%%% may have e.g. created some row or loaded some table, that it +%%% didn't undo (since it failed). +%%%----------------------------------------------------------------- + +init_all(Config0) when list(Config0) -> + ?LOG("init_all -> entry with" + "~n Config0: ~p",[Config0]), + + %% -- + %% Fix config: + %% + + DataDir0 = ?config(data_dir, Config0), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + Config1 = lists:keydelete(data_dir, 1, Config0), + Config = [{data_dir, DataDir3 ++ "/"}|Config1], + + %% -- + %% Start nodes + %% + + ?line {ok, SaNode} = start_node(snmp_sa), + ?line {ok, MgrNode} = start_node(snmp_mgr), + + + %% -- + %% Create necessary files + %% + + Dir = ?config(priv_dir, Config), + ?DBG("init_all -> Dir ~p", [Dir]), + + DataDir = ?config(data_dir, Config), + ?DBG("init_all -> DataDir ~p", [DataDir]), + + file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")), + ?DBG("init_all -> MgrDir ~p", [MgrDir]), + + file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")), + ?DBG("init_all -> AgentDir ~p", [AgentDir]), + + file:make_dir(SaDir = filename:join(Dir, "sa_dir/")), + ?DBG("init_all -> SaDir ~p", [SaDir]), + + + %% -- + %% Start and initiate mnesia + %% + + ?DBG("init_all -> load application mnesia", []), + ?line ok = application:load(mnesia), + + ?DBG("init_all -> load application mnesia on node ~p", [SaNode]), + ?line ok = rpc:call(SaNode, application, load, [mnesia]), + + ?DBG("init_all -> application mnesia: set_env dir",[]), + ?line application_controller:set_env(mnesia, dir, + filename:join(Dir, "Mnesia1")), + + ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]), + ?line rpc:call(SaNode, application_controller, set_env, + [mnesia, dir, filename:join(Dir, "Mnesia2")]), + + ?DBG("init_all -> create mnesia schema",[]), + ?line ok = mnesia:create_schema([SaNode, node()]), + + ?DBG("init_all -> start application mnesia",[]), + ?line ok = application:start(mnesia), + + ?DBG("init_all -> start application mnesia on ~p",[SaNode]), + ?line ok = rpc:call(SaNode, application, start, [mnesia]), + Ip = ?LOCALHOST(), + [{snmp_sa, SaNode}, + {snmp_mgr, MgrNode}, + {agent_dir, AgentDir ++ "/"}, + {mgr_dir, MgrDir ++ "/"}, + {sa_dir, SaDir ++ "/"}, + {mib_dir, DataDir}, + {ip, Ip} | + Config]. + +finish_all(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + stop_node(SaNode), + stop_node(MgrNode), + application:stop(mnesia). + +start_v1_agent(Config) when list(Config) -> + start_agent(Config, [v1]). + +start_v1_agent(Config,Opts) when list(Config), list(Opts) -> + start_agent(Config, [v1], Opts). + +start_v2_agent(Config) when list(Config) -> + start_agent(Config, [v2]). + +start_v3_agent(Config) when list(Config) -> + start_agent(Config, [v3]). + +start_bilingual_agent(Config) when list(Config) -> + start_agent(Config, [v1,v2]). + +start_multi_threaded_agent(Config) when list(Config) -> + start_agent(Config, [v2], [{snmp_multi_threaded, true}]). + +stop_agent(Config) when list(Config) -> + ?LOG("stop_agent -> entry with" + "~n Config: ~p",[Config]), + + {Sup, Par} = ?config(snmp_sup, Config), + ?DBG("stop_agent -> attempt to stop (sup) ~p" + "~n Sup: ~p" + "~n Par: ~p", + [Sup, + (catch process_info(Sup)), + (catch process_info(Par))]), + stop_sup(Sup, Par), + + {Sup2, Par2} = ?config(snmp_sub, Config), + ?DBG("stop_agent -> attempt to stop (sub) ~p" + "~n Sup2: ~p" + "~n Par2: ~p", + [Sup2, + (catch process_info(Sup2)), + (catch process_info(Par2))]), + stop_sup(Sup2, Par2), + + ?DBG("stop_agent -> done - now cleanup config", []), + C1 = lists:keydelete(snmp_sup, 1, Config), + lists:keydelete(snmp_sub, 1, C1). + + +stop_sup(Pid, _) when node(Pid) == node() -> + case (catch process_info(Pid)) of + PI when list(PI) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + exit(Pid, kill), + await_stopped(Pid, Ref); + {'EXIT', _Reason} -> + ?LOG("stop_sup -> ~p not running", [Pid]), + ok + end; +stop_sup(Pid, _) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + ?LOG("stop_sup -> Ref: ~p", [Ref]), + %% Pid ! {'EXIT', Parent, shutdown}, % usch + exit(Pid, kill), + await_stopped(Pid, Ref). + +await_stopped(Pid, Ref) -> + receive + {'DOWN', Ref, process, Pid, _Reason} -> + ?DBG("received down message for ~p", [Pid]), + ok + after 10000 -> + ?INF("await_stopped -> timeout for ~p",[Pid]), + erlang:demonitor(Ref), + ?FAIL({failed_stop,Pid}) + end. + + +start_agent(Config, Vsn) -> + start_agent(Config, Vsn, []). +start_agent(Config, Vsn, Opts) -> + ?LOG("start_agent -> entry (~p) with" + "~n Config: ~p" + "~n Vsn: ~p" + "~n Opts: ~p",[node(), Config, Vsn, Opts]), + + ?line AgentDir = ?config(agent_dir, Config), + ?line SaNode = ?config(snmp_sa, Config), + + snmp_app_env_init(vsn_init(Vsn) ++ + [{audit_trail_log, read_write_log}, + {audit_trail_log_dir, AgentDir}, + {audit_trail_log_size, {10240, 10}}, + {force_config_reload, false}, + {snmp_agent_type, master}, + {snmp_config_dir, AgentDir}, + {snmp_db_dir, AgentDir}, + {snmp_local_db_auto_repair, true}, + {snmp_master_agent_verbosity, trace}, + {snmp_supervisor_verbosity, trace}, + {snmp_mibserver_verbosity, trace}, + {snmp_symbolic_store_verbosity, trace}, + {snmp_note_store_verbosity, trace}, + {snmp_net_if_verbosity, trace}], + Opts), + + + process_flag(trap_exit,true), + + {ok, AppSup} = snmp_app_sup:start_link(), + unlink(AppSup), + ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]), + + ?DBG("start_agent -> start master agent (old style)",[]), + Sup = case (catch snmpa_app:start(normal)) of + {ok, S} -> + ?DBG("start_agent -> started, Sup: ~p",[S]), + S; + + Else -> + ?DBG("start_agent -> unknown result: ~n~p",[Else]), + %% Get info about the apps we depend on + MnesiaInfo = mnesia_running(), + ?FAIL({start_failed,Else,MnesiaInfo}) + end, + + ?DBG("start_agent -> unlink from supervisor",[]), + ?line unlink(Sup), + ?line SaDir = ?config(sa_dir, Config), + ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]), + ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]), + ?DBG("start_agent -> done",[]), + ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config]. + + +vsn_init(Vsn) -> + vsn_init([v1,v2,v3], Vsn, []). + +vsn_init([], _Vsn, Acc) -> + Acc; +vsn_init([V|Vsns], Vsn, Acc) -> + case lists:member(V, Vsn) of + true -> + vsn_init(Vsns, Vsn, [{V, true}|Acc]); + false -> + vsn_init(Vsns, Vsn, [{V, false}|Acc]) + end. + +snmp_app_env_init(Env0, Opts) -> + ?DBG("snmp_app_env_init -> unload snmp",[]), + ?line application:unload(snmp), + ?DBG("snmp_app_env_init -> load snmp",[]), + ?line application:load(snmp), + ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]), + F1 = fun({Key,Val} = New, Acc0) -> + ?DBG("snmp_app_env_init -> " + "updating setting ~p to ~p", [Key, Val]), + case lists:keyreplace(Key, 1, Acc0, New) of + Acc0 -> + [New|Acc0]; + Acc -> + Acc + end + end, + Env = lists:foldr(F1, Env0, Opts), + ?DBG("snmp_app_env_init -> Env: ~p",[Env]), + F2 = fun({Key,Val}) -> + ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]), + application_controller:set_env(snmp, Key, Val) + end, + lists:foreach(F2, Env). + + + + +%% Test if application is running +mnesia_running() -> ?IS_MNESIA_RUNNING(). +crypto_running() -> ?IS_CRYPTO_RUNNING(). + + +start_sub(Dir) -> + ?DBG("start_sub -> entry",[]), + Opts = [{db_dir, Dir}, + {supervisor, [{verbosity, trace}]}], + %% BMK BMK +% {ok, P} = snmp_supervisor:start_sub(Dir), + {ok, P} = snmpa_supervisor:start_sub_sup(Opts), + unlink(P), + {ok, {P, self()}}. + +create_tables(SaNode) -> + ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables}, + {attributes, [a1,a2]}]). + +delete_tables() -> + mnesia:delete_table(friendsTable2), + mnesia:delete_table(kompissTable2), + mnesia:delete_table(snmp_variables). + +%% Creation is done in runtime! +delete_mib_storage_mnesia_tables() -> + mnesia:delete_table(snmpa_mib_data), + mnesia:delete_table(snmpa_mib_tree), + mnesia:delete_table(snmpa_symbolic_store). + +%%----------------------------------------------------------------- +%% A test case is always one of: +%% - v1 specific case +%% - v2 specific case +%% - v1 and v2 case +%% All v1 specific cases are prefixed with v1_, and all v2 with +%% v2_. E.g. v1_trap/v2_trap. +%% +%% All other cases are shared. However, the testserver uses the name +%% of the case to generate a file for that case. The same case cannot +%% be used in different configurations in the same suite. Therefore +%% all these functions exists in two variants, the base function +%% <base>, and a second version <base>_2. There may be several +%% versions as well, <base>_N. +%%----------------------------------------------------------------- +mib_storage(suite) -> [ + mib_storage_ets, + mib_storage_dets, + mib_storage_mnesia, + mib_storage_size_check_ets, + mib_storage_size_check_dets, + mib_storage_size_check_mnesia, + mib_storage_varm_dets, + mib_storage_varm_mnesia + ]. + +mib_storage_ets(suite) -> {req, [], {conf, init_mib_storage_ets, + mib_storage_ets_cases(), + finish_mib_storage_ets}}. + +mib_storage_dets(suite) -> {req, [], {conf, init_mib_storage_dets, + mib_storage_dets_cases(), + finish_mib_storage_dets}}. + +mib_storage_mnesia(suite) -> {req, [], {conf, init_mib_storage_mnesia, + mib_storage_mnesia_cases(), + finish_mib_storage_mnesia}}. + +mib_storage_size_check_ets(suite) -> + {req, [], {conf, + init_size_check_mse, + mse_size_check_cases(), + finish_size_check_mse}}. + +mib_storage_size_check_dets(suite) -> + {req, [], {conf, + init_size_check_msd, + msd_size_check_cases(), + finish_size_check_msd}}. + +mib_storage_size_check_mnesia(suite) -> + {req, [], {conf, + init_size_check_msm, + msm_size_check_cases(), + finish_size_check_msm}}. + +mib_storage_varm_dets(suite) -> + {req, [], {conf, + init_varm_mib_storage_dets, + varm_mib_storage_dets_cases(), + finish_varm_mib_storage_dets}}. + +mib_storage_varm_mnesia(suite) -> + {req, [], {conf, + init_varm_mib_storage_mnesia, + varm_mib_storage_mnesia_cases(), + finish_varm_mib_storage_mnesia}}. + +mib_storage_ets_cases() -> + [ + mse_simple, + mse_v1_processing, + mse_big, + mse_big2, + mse_loop_mib, + mse_api, + mse_sa_register, + mse_v1_trap, + mse_sa_error, + mse_next_across_sa, + mse_undo, + mse_standard_mib, + mse_community_mib, + mse_framework_mib, + mse_target_mib, + mse_notification_mib, + mse_view_based_acm_mib, + mse_sparse_table, + mse_me_of, + mse_mib_of]. + +mib_storage_dets_cases() -> + [ + msd_simple, + msd_v1_processing, + msd_big, + msd_big2, + msd_loop_mib, + msd_api, + msd_sa_register, + msd_v1_trap, + msd_sa_error, + msd_next_across_sa, + msd_undo, + msd_standard_mib, + msd_community_mib, + msd_framework_mib, + msd_target_mib, + msd_notification_mib, + msd_view_based_acm_mib, + msd_sparse_table, + msd_me_of, + msd_mib_of + ]. + +mib_storage_mnesia_cases() -> + [ + msm_simple, + msm_v1_processing, + msm_big, + msm_big2, + msm_loop_mib, + msm_api, + msm_sa_register, + msm_v1_trap, + msm_sa_error, + msm_next_across_sa, + msm_undo, + msm_standard_mib, + msm_community_mib, + msm_framework_mib, + msm_target_mib, + msm_notification_mib, + msm_view_based_acm_mib, + msm_sparse_table, + msm_me_of, + msm_mib_of + ]. + +mse_size_check_cases() -> + [mse_size_check]. + +msd_size_check_cases() -> + [msd_size_check]. + +msm_size_check_cases() -> + [msm_size_check]. + +varm_mib_storage_dets_cases() -> + [msd_varm_mib_start]. + +varm_mib_storage_mnesia_cases() -> + [msm_varm_mib_start]. + +init_mib_storage_ets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,ets}, + init_ms(Config, [MibStorage]). + +init_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + init_ms(Config, [MibStorage]). + +init_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + init_ms(Config, [MibStorage]). + +init_ms(Config, Opts) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts], + [{vsn, v1} | start_v1_agent(Config,Opts1)]. + +init_size_check_mse(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, ets}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msd(Config) when list(Config) -> + AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage, {dets, AgentDir}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msm(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, {mnesia,[]}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_ms(Config, Opts) when list(Config) -> + SaNode = ?GCONF(snmp_sa, Config), + %% We are using v3 here, so crypto must be supported or else... + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + create_tables(SaNode), + AgentDir = ?GCONF(agent_dir, Config), + MgrDir = ?GCONF(mgr_dir, Config), + Ip = ?GCONF(ip, Config), + ?line ok = + config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_agent(Config, [v3], Opts)]. + +init_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_dets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +init_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_mnesia -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +finish_mib_storage_ets(Config) when list(Config) -> + ?LOG("finish_mib_storage_ets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_mib_storage_dets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_dets -> entry", []), + delete_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_size_check_mse(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msd(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msm(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_ms(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + + +%% These are just interface functions to fool the test server +mse_simple(X) -> simple(X). +mse_v1_processing(X) -> v1_processing(X). +mse_big(X) -> big(X). +mse_big2(X) -> big2(X). +mse_loop_mib(X) -> loop_mib(X). +mse_api(X) -> api(X). +mse_sa_register(X) -> sa_register(X). +mse_v1_trap(X) -> v1_trap(X). +mse_sa_error(X) -> sa_error(X). +mse_next_across_sa(X) -> next_across_sa(X). +mse_undo(X) -> undo(X). +mse_standard_mib(X) -> snmp_standard_mib(X). +mse_community_mib(X) -> snmp_community_mib(X). +mse_framework_mib(X) -> snmp_framework_mib(X). +mse_target_mib(X) -> snmp_target_mib(X). +mse_notification_mib(X) -> snmp_notification_mib(X). +mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +mse_sparse_table(X) -> sparse_table(X). +mse_me_of(X) -> ms_me_of(X). +mse_mib_of(X) -> ms_mib_of(X). + +msd_simple(X) -> simple(X). +msd_v1_processing(X) -> v1_processing(X). +msd_big(X) -> big(X). +msd_big2(X) -> big2(X). +msd_loop_mib(X) -> loop_mib(X). +msd_api(X) -> api(X). +msd_sa_register(X) -> sa_register(X). +msd_v1_trap(X) -> v1_trap(X). +msd_sa_error(X) -> sa_error(X). +msd_next_across_sa(X) -> next_across_sa(X). +msd_undo(X) -> undo(X). +msd_standard_mib(X) -> snmp_standard_mib(X). +msd_community_mib(X) -> snmp_community_mib(X). +msd_framework_mib(X) -> snmp_framework_mib(X). +msd_target_mib(X) -> snmp_target_mib(X). +msd_notification_mib(X) -> snmp_notification_mib(X). +msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msd_sparse_table(X) -> sparse_table(X). +msd_me_of(X) -> ms_me_of(X). +msd_mib_of(X) -> ms_mib_of(X). + +msm_simple(X) -> simple(X). +msm_v1_processing(X) -> v1_processing(X). +msm_big(X) -> big(X). +msm_big2(X) -> big2(X). +msm_loop_mib(X) -> loop_mib(X). +msm_api(X) -> api(X). +msm_sa_register(X) -> sa_register(X). +msm_v1_trap(X) -> v1_trap(X). +msm_sa_error(X) -> sa_error(X). +msm_next_across_sa(X) -> next_across_sa(X). +msm_undo(X) -> undo(X). +msm_standard_mib(X) -> snmp_standard_mib(X). +msm_community_mib(X) -> snmp_community_mib(X). +msm_framework_mib(X) -> snmp_framework_mib(X). +msm_target_mib(X) -> snmp_target_mib(X). +msm_notification_mib(X) -> snmp_notification_mib(X). +msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msm_sparse_table(X) -> sparse_table(X). +msm_me_of(X) -> ms_me_of(X). +msm_mib_of(X) -> ms_mib_of(X). + + +mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X). +msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X). +msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X). + +msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X). +msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X). + +ms_size_check(suite) -> []; +ms_size_check(Config) when list(Config) -> + p("ms_size_check..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?LOG("mib server size check...", []), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMPv2-MIB"), + ?line load_master_std("SNMPv2-TM"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMPv2-MIB"), + ?line unload_master("SNMPv2-TM"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + + +varm_mib_start(suite) -> []; +varm_mib_start(Config) when list(Config) -> + p("varm_mib_start..."), + ?LOG("varm_mib_start -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + %% Start the agent + Opts = ?GCONF(agent_opts, Config), + Config1 = start_v1_agent(Config, Opts), + + %% Sleep some in order for the agent to start properly + ?DBG("varm_mib_start -> sleep some (before loading mobs)", []), + ?SLEEP(5000), + + %% Load all the mibs + HardwiredMibs = loaded_mibs(), + ?DBG("varm_mib_start -> load all mibs", []), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + + %% Unload the hardwired mibs + ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []), + ?SLEEP(1000), + ?DBG("varm_mib_start -> unload (hardwired) mibs", []), + ?line unload_mibs(HardwiredMibs), %% unload hardwired + + ?DBG("varm_mib_start -> sleep some (before stopping agent)", []), + ?SLEEP(1000), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + Config2 = stop_agent(Config1), + + %% Sleep some in order for the agent to stop properly + ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []), + ?SLEEP(5000), + + %% Start the agent (again) + ?DBG("varm_mib_start -> start the agent", []), + Config3 = start_v1_agent(Config2, Opts), + + ?DBG("varm_mib_start -> sleep some (before starting tests)", []), + ?SLEEP(5000), + + %% Perform the test(s) + ?DBG("varm_mib_start -> perform the tests", []), + try_test(snmp_community_mib), + try_test(snmp_framework_mib), + try_test(snmp_target_mib), + try_test(snmp_notification_mib), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + stop_agent(Config3), + ok. + + +-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]). +-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]). +-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +ms_me_of(suite) -> []; +ms_me_of(Config) when list(Config) -> + p("ms_me_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = me_of(?snmpTrapCommunity_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = me_of(?vacmViewSpinLock_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +me_of(Oid) -> + case snmpa:me_of(Oid) of + {ok, #me{oid = Oid}} -> + ok; + {ok, #me{oid = OtherOid}} -> + case lists:reverse(Oid) of + [0|Rest] -> + case lists:reverse(Rest) of + OtherOid -> + ok; + AnotherOid -> + {error, {invalid_oid, Oid, AnotherOid}} + end; + _ -> + {error, {invalid_oid, Oid, OtherOid}} + end; + {error, Reason} -> + {error, Reason}; + Else -> + {error, Else} + end. + + +ms_mib_of(suite) -> []; +ms_mib_of(Config) when list(Config) -> + p("ms_mib_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance, + 'SNMP-USER-BASED-SM-MIB'), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +mib_of(Oid, ExpectedMibName) -> + ?DBG("mib_of -> entry with" + "~n Oid: ~p" + "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]), + %% case snmpa:mib_of(Oid) of + MibOf = snmpa:mib_of(Oid), + ?DBG("mib_of -> MibOf: ~n~p", [MibOf]), + case MibOf of + {ok, ExpectedMibName} -> + ok; + {ok, OtherMibName} -> + {error, {invalid_mib, ExpectedMibName, OtherMibName}}; + {error, Reason} -> + {error, Reason}; + Else -> + ?DBG("mib_of -> Else: ~n~p", [Else]), + {error, Else} + end. + + +app_info(suite) -> []; +app_info(Config) when list(Config) -> + SnmpDir = app_dir(snmp), + SslDir = app_dir(ssl), + CryptoDir = app_dir(crypto), + Attr = snmp:module_info(attributes), + AppVsn = + case lists:keysearch(app_vsn, 1, Attr) of + {value, {app_vsn, V}} -> + V; + false -> + "undefined" + end, + io:format("Root dir: ~s~n" + "SNMP: Application dir: ~s~n" + " Application ver: ~s~n" + "SSL: Application dir: ~s~n" + "CRYPTO: Application dir: ~s~n", + [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]), + ok. + +app_dir(App) -> + case code:lib_dir(App) of + D when list(D) -> + filename:basename(D); + {error, _Reason} -> + "undefined" + end. + + +test_v1(suite) -> {req, [], {conf, init_v1, v1_cases(), finish_v1}}. + +%v1_cases() -> [loop_mib]; +v1_cases() -> + [simple, + db_notify_client, + v1_processing, big, big2, loop_mib, + api, subagent, mnesia, multiple_reqs, + sa_register, v1_trap, sa_error, next_across_sa, undo, reported_bugs, + standard_mibs, sparse_table, cnt_64, + opaque, + % opaque]. + + change_target_addr_config]. + +init_v1(Config) when list(Config) -> + ?line SaNode = ?config(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v1} | start_v1_agent(Config)]. + +finish_v1(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v2(suite) -> {req, [], {conf, init_v2, v2_cases(), finish_v2}}. + +%v2_cases() -> [loop_mib_2]; +v2_cases() -> + [simple_2, v2_processing, big_2, big2_2, loop_mib_2, + api_2, subagent_2, mnesia_2, + multiple_reqs_2, sa_register_2, v2_trap, v2_inform, sa_error_2, + next_across_sa_2, undo_2, reported_bugs_2, standard_mibs_2, + v2_types, implied, sparse_table_2, cnt_64_2, opaque_2, v2_caps]. + +init_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_v2_agent(Config)]. + +finish_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v1_v2(suite) -> {req, [], {conf, init_v1_v2, v1_v2_cases(), finish_v1_v2}}. + +v1_v2_cases() -> + [simple_bi]. + +init_v1_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, bilingual} | start_bilingual_agent(Config)]. + +finish_v1_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v3(suite) -> {req, [], {conf, init_v3, v3_cases(), finish_v3}}. + +%v3_cases() -> [loop_mib_3]; +v3_cases() -> + [simple_3, v3_processing, + big_3, big2_3, api_3, subagent_3, mnesia_3, loop_mib_3, + multiple_reqs_3, sa_register_3, v3_trap, v3_inform, sa_error_3, + next_across_sa_3, undo_3, reported_bugs_3, standard_mibs_3, + v3_security, + v2_types_3, implied_3, sparse_table_3, cnt_64_3, opaque_3, v2_caps_3]. + +init_v3(Config) when list(Config) -> + %% Make sure crypto works, otherwise start_agent will fail + %% and we will be stuck with a bunch of mnesia tables for + %% the rest of this suite... + ?DBG("start_agent -> start crypto app",[]), + case os:type() of + vxworks -> + no_crypto; + _ -> + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end + end, + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v3], MgrDir, AgentDir, + tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_v3_agent(Config)]. + +finish_v3(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_multi_threaded(suite) -> {req, [], {conf, init_mt, mt_cases(), finish_mt}}. + +mt_cases() -> + [multi_threaded, mt_trap]. + +init_mt(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_multi_threaded_agent(Config)]. + +finish_mt(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +%% This one *must* be run first in each case. +init_case(Config) when list(Config) -> + ?DBG("init_case -> entry with" + "~n Config: ~p", [Config]), + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + MasterNode = node(), + + SaHost = ?HOSTNAME(SaNode), + MgrHost = ?HOSTNAME(MgrNode), + MasterHost = ?HOSTNAME(MasterNode), + {ok, MasterIP} = snmp_misc:ip(MasterHost), + {ok, MIP} = snmp_misc:ip(MgrHost), + {ok, SIP} = snmp_misc:ip(SaHost), + + + put(mgr_node, MgrNode), + put(sa_node, SaNode), + put(master_node, MasterNode), + put(sa_host, SaHost), + put(mgr_host, MgrHost), + put(master_host, MasterHost), + put(mip, tuple_to_list(MIP)), + put(masterip , tuple_to_list(MasterIP)), + put(sip, tuple_to_list(SIP)), + + MibDir = ?config(mib_dir, Config), + put(mib_dir, MibDir), + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + put(std_mib_dir, StdM), + + MgrDir = ?config(mgr_dir, Config), + put(mgr_dir, MgrDir), + + put(vsn, ?config(vsn, Config)), + ?DBG("init_case -> exit with" + "~n MasterNode: ~p" + "~n SaNode: ~p" + "~n MgrNode: ~p" + "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]), + {SaNode, MgrNode, MibDir}. + +load_master(Mib) -> + ?DBG("load_master -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]). + +load_master_std(Mib) -> + ?DBG("load_master_std -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]). + +unload_master(Mib) -> + ?DBG("unload_master -> entry with" + "~n Mib: ~p", [Mib]), + ok = snmpa:unload_mibs(snmp_master_agent, [Mib]). + +loaded_mibs() -> + ?DBG("loaded_mibs -> entry",[]), + Info = snmpa:info(snmp_master_agent), + {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info), + [atom_to_list(Mib) || {Mib,_,_} <- Mibs]. + +unload_mibs(Mibs) -> + ?DBG("unload_mibs -> entry with" + "~n Mibs: ~p", [Mibs]), + ok = snmpa:unload_mibs(snmp_master_agent, Mibs). + +start_subagent(SaNode, RegTree, Mib) -> + ?DBG("start_subagent -> entry with" + "~n SaNode: ~p" + "~n RegTree: ~p" + "~n Mib: ~p", [SaNode, RegTree, Mib]), + MA = whereis(snmp_master_agent), + ?DBG("start_subagent -> MA: ~p", [MA]), + MibDir = get(mib_dir), + Mib1 = join(MibDir,Mib), + %% BMK BMK +% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of + case rpc:call(SaNode, snmpa_supervisor, + start_sub_agent, [MA, RegTree, [Mib1]]) of + {ok, SA} -> + ?DBG("start_subagent -> SA: ~p", [SA]), + {ok, SA}; + Error -> + ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]}) + end. + +stop_subagent(SA) -> + ?DBG("stop_subagent -> entry with" + "~n SA: ~p", [SA]), + %% BNK BMK + %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]). + rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]). + +%%----------------------------------------------------------------- +%% This function takes care of the old OTP-SNMPEA-MIB. +%% Unfortunately, the testcases were written to use the data in the +%% internal tables, and these table are now obsolete and not used +%% by the agent. Therefore, we emulate them by using +%% OLD-SNMPEA-MIB, which uses the default impl. of all tables. +%% +%% These two rows must exist in intCommunityTable +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. +%% (But with the manager's IP address) +%% +%%----------------------------------------------------------------- +init_old() -> + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [6 | "public"], + {get(mip), "public", 2, 2}), + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [13 | "standard trap"], + {get(mip), "standard trap", 2, 1}), + snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]). + + + +simple(suite) -> []; +simple(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(simple_standard_test). + +simple_2(X) -> simple(X). + +simple_bi(suite) -> []; +simple_bi(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(vsn, v1), % First, try v1 manager + try_test(simple_standard_test), + + put(vsn, v2), % Then, try v2 manager + try_test(simple_standard_test). + +simple_3(X) -> + simple(X). + +big(suite) -> []; +big(Config) when list(Config) -> + ?DBG("big -> entry", []), + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?DBG("big -> SA: ~p", [SA]), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB"). + +big_2(X) -> big(X). + +big_3(X) -> big(X). + + +big2(suite) -> []; +big2(Config) when list(Config) -> + %% This is exactly the same tests as 'big', but with the + %% v2 equivalent of the mibs. + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"), + ?line load_master("OLD-SNMPEA-MIB-v2"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB-v2"). + +big2_2(X) -> big2(X). + +big2_3(X) -> big2(X). + + +multi_threaded(suite) -> []; +multi_threaded(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(multi_threaded_test), + ?line unload_master("Test1"). + +mt_trap(suite) -> []; +mt_trap(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + ?line load_master("TestTrapv2"), + try_test(mt_trap_test, [MA]), + ?line unload_master("TestTrapv2"), + ?line unload_master("Test1"). + +v2_types(suite) -> []; +v2_types(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(types_v2_test), + ?line unload_master("Test1"). + +v2_types_3(X) -> v2_types(X). + + +implied(suite) -> []; +implied(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(implied_test,[MA]), + ?line unload_master("Test1"). + +implied_3(X) -> implied(X). + + +sparse_table(suite) -> []; +sparse_table(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(sparse_table_test), + ?line unload_master("Test1"). + +sparse_table_2(X) -> sparse_table(X). + +sparse_table_3(X) -> sparse_table(X). + +cnt_64(suite) -> []; +cnt_64(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(cnt_64_test, [MA]), + ?line unload_master("Test1"). + +cnt_64_2(X) -> cnt_64(X). + +cnt_64_3(X) -> cnt_64(X). + +opaque(suite) -> []; +opaque(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(opaque_test), + ?line unload_master("Test1"). + +opaque_2(X) -> opaque(X). + +opaque_3(X) -> opaque(X). + + +change_target_addr_config(suite) -> []; +change_target_addr_config(Config) when list(Config) -> + p("Testing changing target address config..."), + ?LOG("change_target_addr_config -> entry",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(sname,snmp_suite), + put(verbosity,trace), + + MA = whereis(snmp_master_agent), + + ?LOG("change_target_addr_config -> load TestTrap",[]), + ?line load_master("TestTrap"), + + ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,trace), + + %% First send some traps that will arive att the original manager + ?LOG("change_target_addr_config -> send trap",[]), + try_test(ma_trap1, [MA]), + + ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,silence), + + %% Start new dummy listener + ?LOG("change_target_addr_config -> start dummy manager",[]), + ?line {ok,Pid,NewPort} = dummy_manager_start(MA), + + %% Reconfigure + ?LOG("change_target_addr_config -> reconfigure",[]), + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_addr_conf(AgentDir, NewPort), + ?line snmp_target_mib:reconfigure(AgentDir), + + %% Send the trap again + ?LOG("change_target_addr_config -> send trap again",[]), + catch dummy_manager_send_trap2(Pid), + + ?LOG("change_target_addr_config -> await trap ack",[]), + catch dummy_manager_await_trap2_ack(), + + ?LOG("change_target_addr_config -> stop dummy manager",[]), + ?line ok = dummy_manager_stop(Pid), + + ?LOG("change_target_addr_config -> reset target address config",[]), + ?line reset_target_addr_conf(AgentDir), + + ?LOG("change_target_addr_config -> unload TestTrap",[]), + ?line unload_master("TestTrap"). + + +dummy_manager_start(MA) -> + ?DBG("dummy_manager_start -> entry",[]), + Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]), + ?DBG("dummy_manager_start -> Pid: ~p",[Pid]), + await_dummy_manager_started(Pid). + +await_dummy_manager_started(Pid) -> + receive + {dummy_manager_started,Pid,Port} -> + ?DBG("dummy_manager_start -> acknowledge received with" + "~n Port: ~p",[Port]), + {ok,Pid,Port}; + {'EXIT', Pid, Reason} -> + {error, Pid, Reason}; + O -> + ?LOG("dummy_manager_start -> received unknown message:" + "~n ~p",[O]), + await_dummy_manager_started(Pid) + end. + +dummy_manager_stop(Pid) -> + ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]), + Pid ! stop, + receive + {dummy_manager_stopping, Pid} -> + ?DBG("dummy_manager_stop -> acknowledge received",[]), + ok + after 10000 -> + ?ERR("dummy_manager_stop -> timeout",[]), + timeout + end. + +dummy_manager_send_trap2(Pid) -> + ?DBG("dummy_manager_send_trap2 -> entry",[]), + Pid ! {send_trap,testTrap2}. + +dummy_manager_await_trap2_ack() -> + ?DBG("dummy_manager_await_trap2 -> entry",[]), + receive + {received_trap,Trap} -> + ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]), + %% Note: + %% Without this sleep the v2_inform_i testcase failes! There + %% is no relation between these two test cases as far as I + %% able to figure out... + sleep(60000), + ok; + O -> + ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]), + ok + after 10000 -> + ?ERR("dummy_manager_await_trap2 -> timeout",[]), + timeout + end. + +dummy_manager_init(Parent,MA) -> + ?DBG("dummy_manager_init -> entry with" + "~n Parent: ~p" + "~n MA: ~p",[Parent,MA]), + {ok,S} = gen_udp:open(0,[{recbuf,65535}]), + ?DBG("dummy_manager_init -> S: ~p",[S]), + {ok,Port} = inet:port(S), + ?DBG("dummy_manager_init -> Port: ~p",[Port]), + Parent ! {dummy_manager_started,self(),Port}, + dummy_manager_loop(Parent,S,MA). + +dummy_manager_loop(P,S,MA) -> + ?LOG("dummy_manager_loop -> ready for receive",[]), + receive + {send_trap,Trap} -> + ?LOG("dummy_manager_loop -> received trap send request" + "~n Trap: ~p",[Trap]), + snmpa:send_trap(MA, Trap, "standard trap"), + dummy_manager_loop(P,S,MA); + {udp, _UdpId, Ip, UdpPort, Bytes} -> + ?LOG("dummy_manager_loop -> received upd message" + "~n from: ~p:~p" + "~n size: ~p", + [Ip, UdpPort, dummy_manager_message_sz(Bytes)]), + R = dummy_manager_handle_message(Bytes), + ?DBG("dummy_manager_loop -> R: ~p",[R]), + P ! R, + dummy_manager_loop(P,S,MA); + stop -> + ?DBG("dummy_manager_loop -> received stop request",[]), + P ! {dummy_manager_stopping, self()}, + gen_udp:close(S), + exit(normal); + O -> + ?LOG("dummy_manager_loop -> received unknown message:" + "~n ~p",[O]), + dummy_manager_loop(P,S,MA) + end. + +dummy_manager_message_sz(B) when binary(B) -> + size(B); +dummy_manager_message_sz(L) when list(L) -> + length(L); +dummy_manager_message_sz(_) -> + undefined. + +dummy_manager_handle_message(Bytes) -> + case (catch snmp_pdus:dec_message(Bytes)) of + {'EXIT',Reason} -> + ?ERR("dummy_manager_handle_message -> " + "failed decoding message only:~n ~p",[Reason]), + {error,Reason}; + M -> + ?DBG("dummy_manager_handle_message -> decoded message:" + "~n ~p",[M]), + {received_trap,M} + end. + + +api(suite) -> []; +api(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(api_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +api_2(X) -> api(X). + +api_3(X) -> api(X). + + +subagent(suite) -> []; +subagent(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + try_test(load_test_sa), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + + p("Loading previous subagent mib in master and testing..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]), + try_test(load_test), + + p("Unloading previous subagent mib in master and testing..."), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]), + try_test(unreg_test), + p("Testing register subagent..."), + rpc:call(SaNode, snmp, register_subagent, + [MA, ?klas1, SA]), + try_test(load_test_sa), + + ?line stop_subagent(SA), + try_test(unreg_test). + +subagent_2(X) -> subagent(X). + +subagent_3(X) -> subagent(X). + + +mnesia(suite) -> []; +mnesia(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent with mnesia impl..."), + {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + try_test(big_test_2), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA). + +mnesia_2(X) -> mnesia(X). + +mnesia_3(X) -> mnesia(X). + + +multiple_reqs(suite) -> + {req, [], {conf, init_mul, mul_cases(), finish_mul}}. + +mul_cases() -> + [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err]. + +multiple_reqs_2(suite) -> + {req, [], {conf, init_mul, mul_cases_2(), finish_mul}}. + +multiple_reqs_3(_X) -> + {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}. + + +mul_cases_2() -> + [mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2, mul_set_err_2]. + + +mul_cases_3() -> + [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3]. + + +init_mul(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + [{mul_sub, SA} | Config]. + +finish_mul(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + SA = ?config(mul_sub, Config), + + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA), + lists:keydelete(mul_sub, 1, Config). + +mul_get(suite) -> []; +mul_get(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get..."), + try_test(do_mul_get). + +mul_get_2(X) -> mul_get(X). + +mul_get_3(X) -> mul_get(X). + + +mul_get_err(suite) -> []; +mul_get_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get with error..."), + try_test(do_mul_get_err). + +mul_get_err_2(X) -> mul_get_err(X). + +mul_get_err_3(X) -> mul_get_err(X). + + +mul_next(suite) -> []; +mul_next(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next). + +mul_next_2(X) -> mul_next(X). + +mul_next_3(X) -> mul_next(X). + + +mul_next_err(suite) -> []; +mul_next_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next_err). + +mul_next_err_2(X) -> mul_next_err(X). + +mul_next_err_3(X) -> mul_next_err(X). + + +mul_set(suite) -> []; +mul_set(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set..."), + try_test(do_mul_set). + +mul_set_2(X) -> mul_set(X). + +mul_set_3(X) -> mul_set(X). + + +mul_set_err(suite) -> []; +mul_set_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set with error..."), + try_test(do_mul_set_err). + +mul_set_err_2(X) -> mul_set_err(X). + +mul_set_err_3(X) -> mul_set_err(X). + + +sa_register(suite) -> []; +sa_register(Config) when list(Config) -> + ?DBG("sa_register -> entry", []), + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?DBG("sa_register -> start subagent", []), + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + + ?DBG("sa_register -> unregister subagent", []), + p("Testing unregister subagent (2)..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Loading SA-MIB..."), + ?DBG("sa_register -> unload mibs", []), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + ?DBG("sa_register -> unload mibs", []), + snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]), + ?DBG("sa_register -> register subagent", []), + rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]), + try_test(sa_mib), + + ?DBG("sa_register -> stop subagent", []), + ?line stop_subagent(SA). + +sa_register_2(X) -> sa_register(X). + +sa_register_3(X) -> sa_register(X). + + +v1_trap(suite) -> []; +v1_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_trap1, [MA]), + try_test(ma_trap2, [MA]), + try_test(ma_v2_2_v1_trap, [MA]), + try_test(ma_v2_2_v1_trap2, [MA]), + + p("Testing trap sending from subagent..."), + try_test(sa_trap1, [SA]), + try_test(sa_trap2, [SA]), + try_test(sa_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v2_trap(suite) -> []; +v2_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + + try_test(ma_v2_trap1, [MA]), + try_test(ma_v2_trap2, [MA]), + try_test(ma_v1_2_v2_trap, [MA]), + try_test(ma_v1_2_v2_trap2, [MA]), + + try_test(sa_mib), + p("Testing trap sending from subagent..."), + try_test(sa_v1_2_v2_trap1, [SA]), + try_test(sa_v1_2_v2_trap2, [SA]), + try_test(sa_v1_2_v2_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v3_trap(X) -> + v2_trap(X). + +v2_inform(suite) -> + {req, [], {conf, init_v2_inform, [v2_inform_i], finish_v2_inform}}. + +v3_inform(_X) -> + %% v2_inform(X). + {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}. + +init_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +init_v3_inform(X) -> + init_v2_inform(X). + +finish_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +finish_v3_inform(X) -> + finish_v2_inform(X). + + + +v2_inform_i(suite) -> []; +v2_inform_i(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing inform sending from master agent... NOTE! This test\ntakes a " + "few minutes (5) to complete."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_v2_inform1, [MA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"). + +v3_inform_i(X) -> v2_inform_i(X). + + +sa_error(suite) -> []; +sa_error(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing sa bad value (is_set_ok)..."), + try_test(sa_errs_bad_value), + + p("Testing sa gen err (set)..."), + try_test(sa_errs_gen_err), + + p("Testing too big..."), + try_test(sa_too_big), + + ?line unload_master("OLD-SNMPEA-MIB"), + stop_subagent(SA). + +sa_error_2(X) -> sa_error(X). + +sa_error_3(X) -> sa_error(X). + + +next_across_sa(suite) -> []; +next_across_sa(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Loading another subagent mib..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]), + + rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]), + try_test(load_test_sa), + + p("Testing next across subagent (endOfMibView from SA)..."), + try_test(next_across_sa), + + p("Unloading mib"), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Starting another subagent"), + ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"), + p("Testing next across subagent (wrong prefix from SA)..."), + try_test(next_across_sa), + + stop_subagent(SA), + stop_subagent(SA2). + +next_across_sa_2(X) -> next_across_sa(X). + +next_across_sa_3(X) -> next_across_sa(X). + + +undo(suite) -> []; +undo(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing undo phase at master agent..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]), + try_test(undo_test), + try_test(api_test2), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]), + + p("Testing bad return values from instrum. funcs..."), + try_test(bad_return), + + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]), + + p("Testing undo phase at subagent..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]), + ?line ok = snmpa:register_subagent(MA, ?klas3, SA), + ?line ok = snmpa:register_subagent(MA, ?klas4, SA), + try_test(undo_test), + try_test(api_test3), + + p("Testing undo phase across master/subagents..."), + try_test(undo_test), + try_test(api_test3), + stop_subagent(SA). + +undo_2(X) -> undo(X). + +undo_3(X) -> undo(X). + +%% Req. Test2 +v1_processing(suite) -> []; +v1_processing(Config) when list(Config) -> + ?DBG("v1_processing -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v1_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v2_processing(suite) -> []; +v2_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v3_processing(suite) -> []; +v3_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), % same as v2! + ?line unload_master("Test2"). + + +%% We'll try get/set/trap and inform for all the auth & priv protocols. +%% For informs, the mgr is auth-engine. The agent has to sync. This is +%% accomplished by the first inform sent. That one will generate a +%% report, which makes it in sync. The notification-generating +%% application times out, and send again. This time it'll work. +v3_security(suite) -> [v3_crypto_basic, v3_md5_auth, v3_sha_auth, v3_des_priv]. + +v3_crypto_basic(suite) -> []; +v3_crypto_basic(_Config) -> + EID = [0,0,0,0,0,0,0,0,0,0,0,2], + %% From rfc2274 appendix A.3.1 + ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID), + ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f, + 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] = + KMd5_1, + %% From rfc2274 appendix A.3.2 + ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID), + ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23, + 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] = + KSHA_1, + %% From rfc2274, appendix A.5.1 + ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9, + 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] = + snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + %% From rfc2274, appendix A.5.2 + ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4, + 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db, + 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + KSHA_1t = lists:sublist(KSHA_1, 16), + KSHA_2t = lists:sublist(KSHA_2, 16), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b, + 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + + %% Try with correct random + ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2), + ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1), + ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2), + ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2), + ok. + + + +v3_md5_auth(suite) -> []; +v3_md5_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing MD5 authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authMD5"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_sha_auth(suite) -> []; +v3_sha_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing SHA authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authSHA"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_des_priv(suite) -> []; +v3_des_priv(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing DES encryption...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +%% Make sure mgr is in sync with agent +v3_sync(Funcs) -> + ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]), + g([[sysDescr, 0]]), + expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]), + g([[sysDescr, 0]]), + expect(433, [{[sysDescr,0], any}]), + lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs). + +v3_inform_sync(MA) -> + ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, + "standard inform", []), + %% Make sure agent is in sync with mgr... + ?DBG("v3_sync -> wait some time: ",[]), + sleep(20000), % more than 1500*10 in target_addr.conf + ?DBG("v3_sync -> await response",[]), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]). + + +v2_caps(suite) -> []; +v2_caps(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(v2_caps_i, [node()]). + +v2_caps_3(X) -> v2_caps(X). + + +v2_caps_i(Node) -> + ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]), + g([[sysORID, Idx], [sysORDescr, Idx]]), + ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]}, + {[sysORDescr, Idx], "test cap"}]), + ?line rpc:call(Node, snmp, del_agent_caps, [Idx]), + g([[sysORID, Idx]]), + ?line expect(2, [{[sysORID, Idx], noSuchInstance}]). + + +%% Req. Test2 +v1_proc() -> + ?DBG("v1_proc -> entry", []), + %% According to RFC1157. + %% Template: <Section>:<list no> + v1_get_p(), + v1_get_next_p(), + v1_set_p(). + + +v1_get_p() -> + %% 4.1.2:1 + g([[test2]]), + ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]), + g([[tDescr]]), + ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]), + g([[tDescr2,0]]), + ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]), + g([[tDescr3,0]]), + ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]), + g([[tDescr4,0]]), + ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'}, + {[tDescr,0], 'NULL'}]), + g([[sysDescr,3]]), + ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]), + + %% 4.1.2:2 + g([[tTable]]), + ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]), + g([[tEntry]]), + ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]), + + %% 4.1.2:3 + g([[tTooBig, 0]]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.2:4 + g([[tGenErr1, 0]]), + ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]). + + +v1_get_next_p() -> + %% 4.1.3:1 + gn([[1,3,7,1]]), + ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]), + gn([[tDescr2]]), + ?line expect(11, tooBig, 0, any), + + %% 4.1.3:2 + gn([[tTooBig]]), + io:format("We currently don't handle tooBig correct!!!\n"), +% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]), + ?line expect(20, tooBig, 0, any), + + %% 4.1.3:3 + gn([[tGenErr1]]), +% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]), + ?line expect(40, genErr, 1, any), + gn([[tGenErr2]]), +% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]), + ?line expect(41, genErr, 1, any), + gn([[sysDescr], [tGenErr3]]), +% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'}, +% {[tGenErr3], 'NULL'}]). + ?line expect(42, genErr, 2, any). + +v1_set_p() -> + %% 4.1.5:1 + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]), + s([{[tDescr3], s, "noSuchObject"}]), + ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]), + s([{[tDescr3,1], s, "noSuchInstance"}]), + ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]), + s([{[tDescr2,0], s, "inconsistentName"}]), + ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]), + + %% 4.1.5:2 + s([{[tDescr2, 0], i, 4}]), + ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.1.5:3 + %% The standard is quite incorrect here. The resp pdu was too big. In + %% the resp pdu, we have the original vbs. In the tooBig pdu we still + %% have to original vbs => the tooBig pdu is too big as well!!! It + %% may not get it to the manager, unless the agent uses 'NULL' instead + %% of the std-like original value. + s([{[tTooBig, 0], s, ?tooBigStr}]), + %% according to std: +% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.5:4 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]), + s([{[tDescr2, 0], s, "commit_fail"}]), + ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]). + +%% Req. Test2 +v2_proc() -> + %% According to RFC1905. + %% Template: <Section>:<list no> + ?DBG("v2_proc -> entry",[]), + v2_get_p(), + v2_get_next_p(), + v2_get_bulk_p(), + v2_set_p(). + +v2_get_p() -> + %% 4.2.1:2 + ?DBG("v2_get_p -> entry",[]), + g([[test2]]), + ?line expect(10, [{[test2], noSuchObject}]), + g([[tDescr]]), + ?line expect(11, [{[tDescr], noSuchObject}]), + g([[tDescr4,0]]), + ?line expect(12, [{[tDescr4,0], noSuchObject}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}, + {[tDescr,0], noSuchObject}]), + g([[tTable]]), + ?line expect(14, [{[tTable], noSuchObject}]), + g([[tEntry]]), + ?line expect(15, [{[tEntry], noSuchObject}]), + + %% 4.2.1:3 + g([[tDescr2,0]]), %% instrum ret noSuchName!!! + ?line expect(20, [{[tDescr2,0], noSuchInstance}]), + g([[tDescr3,0]]), + ?line expect(21, [{[tDescr3,0], noSuchInstance}]), + g([[sysDescr,3]]), + ?line expect(22, [{[sysDescr, 3], noSuchInstance}]), + g([[tIndex,1]]), + ?line expect(23, [{[tIndex, 1], noSuchInstance}]), + + %% 4.2.1 - any other error: genErr + g([[tGenErr1, 0]]), + ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]), + + %% 4.2.1 - tooBig + g([[tTooBig, 0]]), + ?line expect(40, tooBig, 0, []). + + +v2_get_next_p() -> + %% 4.2.2:2 + ?DBG("v2_get_next_p -> entry",[]), + gn([[1,3,7,1]]), + ?line expect(10, [{[1,3,7,1], endOfMibView}]), + gn([[sysDescr], [1,3,7,1]]), + ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gn([[tCnt2, 1]]), + ?line expect(12, [{[tCnt2,2], 100}]), + gn([[tCnt2, 2]]), + ?line expect(12, [{[tCnt2,2], endOfMibView}]), + + %% 4.2.2 - any other error: genErr + gn([[tGenErr1]]), + ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]), + gn([[tGenErr2]]), + ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]), + gn([[sysDescr], [tGenErr3]]), + ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'}, + {[tGenErr3], 'NULL'}]), + + %% 4.2.2 - tooBig + gn([[tTooBig]]), + ?line expect(20, tooBig, 0, []). + +v2_get_bulk_p() -> + %% 4.2.3 + ?DBG("v2_get_bulk_p -> entry",[]), + gb(1, 1, []), + ?line expect(10, []), + gb(-1, 1, []), + ?line expect(11, []), + gb(-1, -1, []), + ?line expect(12, []), + gb(-1, -1, []), + ?line expect(13, []), + gb(2, 0, [[sysDescr], [1,3,7,1]]), + ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(1, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(0, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]), + ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]), + ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[sysDescr, 0], "Erlang SNMP agent"}]), + + gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig. + ?line expect(19, []), + + gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]), + ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'}, + {[sysObjectID], 'NULL'}, + {[tGenErr1], 'NULL'}, + {[sysDescr], 'NULL'}]), + gb(0, 2, [[tCnt2, 1]]), + ?line expect(21, [{[tCnt2,2], 100}, + {[tCnt2,2], endOfMibView}]). + + +v2_set_p() -> + %% 4.2.5:1 + ?DBG("v2_set_p -> entry",[]), + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]), + + %% 4.2.5:2 + s([{[1,3,6,1,0], s, "noSuchObject"}]), + ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]), + + %% 4.2.5:3 + s([{[tDescr2, 0], i, 4}]), + ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.2.5:4 + s([{[tStr, 0], s, ""}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]), + s([{[tStr, 0], s, "12345"}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]), + + %% 4.2.5:5 - N/A + + %% 4.2.5:6 + s([{[tInt1, 0], i, 0}]), + ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]), + s([{[tInt1, 0], i, 5}]), + ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]), + s([{[tInt2, 0], i, 0}]), + ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]), + s([{[tInt2, 0], i, 5}]), + ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]), + s([{[tInt3, 0], i, 5}]), + ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]), + + %% 4.2.5:7 + s([{[tDescrX, 1, 1], s, "noCreation"}]), + ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]), + + %% 4.2.5:8 + s([{[tDescrX, 1, 2], s, "inconsistentName"}]), + ?line expect(80, inconsistentName, 1, + [{[tDescrX, 1, 2], "inconsistentName"}]), + + %% 4.2.5:9 + s([{[tCnt, 1, 2], i, 5}]), + ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]), + + %% 4.2.5:10 + s([{[tDescr2,0], s, "inconsistentValue"}]), + ?line expect(100, inconsistentValue, 1, + [{[tDescr2,0], "inconsistentValue"}]), + + %% 4.2.5:11 + s([{[tDescr2,0], s, "resourceUnavailable"}]), + ?line expect(110, resourceUnavailable, 1, + [{[tDescr2,0],"resourceUnavailable"}]), + + %% 4.2.5:12 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]). + + %% commitFailed and undoFailed is tested by the 'undo' case. + + +%% Req. OLD-SNMPEA-MIB +table_test() -> + io:format("Testing simple get, next and set on communityTable...~n"), +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. + Key1c3 = [intCommunityViewIndex,get(mip),is("public")], + Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")], + Key1c4 = [intCommunityAccess,get(mip),is("public")], + EndKey = [intCommunityEntry,[9],get(mip),is("public")], + gn([[intCommunityEntry]]), + ?line expect(7, [{Key1c3, 2}]), + gn([[intCommunityTable]]), + ?line expect(71, [{Key1c3, 2}]), + gn([[community]]), + ?line expect(72, [{Key1c3, 2}]), + gn([[otpSnmpeaMIB]]), + ?line expect(73, [{Key1c3, 2}]), + gn([[ericsson]]), + ?line expect(74, [{Key1c3, 2}]), + gn([Key1c3]), + ?line expect(8, [{Key2c3, 2}]), + gn([Key2c3]), + ?line expect(9, [{Key1c4, 2}]), + gn([EndKey]), + AgentIp = [intAgentIpAddress,0], + ?line expect(10, [{AgentIp, any}]), + g([Key1c3]), + ?line expect(11, [{Key1c3, 2}]), + g([EndKey]), + ?line ?v1_2(expect(12, noSuchName, 1, any), + expect(12, [{EndKey, noSuchObject}])), + + io:format("Testing row creation/deletion on communityTable...~n"), + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + s([{NewKeyc5, ?createAndGo}]), + ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any), + s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]), + ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]), + g([NewKeyc4]), + ?line expect(16, [{NewKeyc4, 2}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(17, [{NewKeyc5, ?destroy}]), + s([{NewKeyc4, 2}]), + ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]), + s([{NewKeyc5, ?createAndWait}]), + ?line expect(19, [{NewKeyc5, ?createAndWait}]), + g([NewKeyc5]), + ?line expect(20, [{NewKeyc5, ?notReady}]), + s([{NewKeyc4, 2}]), + ?line expect(21, [{NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(22, [{NewKeyc5, ?notReady}]), + s([{NewKeyc3, 2}]), + ?line expect(23, [{NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(24, [{NewKeyc5, ?notInService}]), + s([{NewKeyc5, ?active}]), + ?line expect(25, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(26, [{NewKeyc5, ?destroy}]), + s([{NewKeyc3, 3}]), + ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]), + otp_1128(). + +%% Req. system group +simple_standard_test() -> + ?DBG("simple_standard_test -> entry",[]), + gn([[1,1]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3]]), + ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6]]), + ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1]]), + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2]]), + ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1]]), + ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1,1]]), + ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[sysDescr]]), + ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr,0]]), + ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr]]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{[sysDescr], noSuchObject}])), + g([[1,6,7,0]]), + ?line ?v1_2(expect(41, noSuchName, 1, any), + expect(3, [{[1,6,7,0], noSuchObject}])), + gn([[1,13]]), + ?line ?v1_2(expect(4, noSuchName,1, any), + expect(4, [{[1,13], endOfMibView}])), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + g([[sysLocation, 0]]), + ?line expect(6, [{[sysLocation, 0], "new_value"}]), + io:format("Testing noSuchName and badValue...~n"), + s([{[sysServices,0], 3}]), + ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any), + s([{[sysLocation, 0], i, 3}]), + ?line expect(62, ?v1_2(badValue, wrongType), 1, any), + ?DBG("simple_standard_test -> done",[]), + ok. + +%% This is run in the agent node +db_notify_client(suite) -> []; +db_notify_client(Config) when list(Config) -> + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p", + [SaNode,MgrNode,MibDir]), + snmpa_local_db:register_notify_client(self(),?MODULE), + + %% This call (the manager) will issue to set operations, so + %% we expect to receive to notify(insert) calls. + try_test(db_notify_client_test), + + ?DBG("await first notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok + end, + + ?DBG("await second notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok + end, + + snmpa_local_db:unregister_notify_client(self()). + + +%% This is run in the manager node +db_notify_client_test() -> + ?DBG("set first new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + + ?DBG("set second new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]). + +notify(Pid,What) -> + ?DBG("notify(~p,~p) -> called",[Pid,What]), + Pid ! {db_notify_test_reply,What}. + + +%% Req: system group, OLD-SNMPEA-MIB, Klas1 +big_test() -> + ?DBG("big_test -> testing simple next/get/set @ master agent...",[]), + simple_standard_test(), + + ?DBG("big_test -> testing simple next/get/set @ subagent...",[]), + gn([[klas1]]), + ?line expect(1, [{[fname,0], ""}]), + g([[fname,0]]), + ?line expect(2, [{[fname,0], ""}]), + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[fname,0]]), + ?line expect(4, [{[fname,0], "test set"}]), + + ?DBG("big_test -> " + "testing next from last instance in master to subagent...",[]), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname,0], "test set"}]), + s([{[fname,0], s, ""}]), + ?line expect(52, [{[fname,0], ""}]), + + table_test(), + + ?DBG("big_test -> adding one row in subagent table",[]), + _FTab = [friendsEntry], + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {[friendsEntry, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [friendsEntry, [3, 3]]]), + ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?active}]), + s([{[friendsEntry, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]), + + otp_1131(), + + ?DBG("big_test -> adding two rows in subagent table with special INDEX", + []), + s([{[kompissEntry, [1, 3]], s, "kompis3"}, + {[kompissEntry, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?createAndGo}]), + g([[kompissEntry, [1, 3]], + [kompissEntry, [2, 3]]]), + ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + gn([[kompissEntry, [1]], + [kompissEntry, [2]]]), + ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + s([{[kompissEntry, [1, 2]], s, "kompis3"}, + {[kompissEntry, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?createAndGo}]), + gn([[kompissEntry, [1, 1]], + [kompissEntry, [2, 1]]]), + ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?active}]), + s([{[kompissEntry, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]), + s([{[kompissEntry, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]), + ?DBG("big_test -> done",[]), + ok. + +%% Req. system group, Klas2, OLD-SNMPEA-MIB +big_test_2() -> + p("Testing simple next/get/set @ master agent (2)..."), + simple_standard_test(), + + p("Testing simple next/get/set @ subagent (2)..."), + gn([[klas2]]), + ?line expect(1, [{[fname2,0], ""}]), + g([[fname2,0]]), + ?line expect(2, [{[fname2,0], ""}]), + s([{[fname2,0], s, "test set"}]), + ?line expect(3, [{[fname2,0], "test set"}]), + g([[fname2,0]]), + ?line expect(4, [{[fname2,0], "test set"}]), + + otp_1298(), + + p("Testing next from last object in master to subagent (2)..."), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname2,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname2,0], "test set"}]), + + table_test(), + + p("Adding one row in subagent table (2)"), + _FTab = [friendsEntry2], + s([{[friendsEntry2, [2, 3]], s, "kompis3"}, + {[friendsEntry2, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?createAndGo}]), + g([[friendsEntry2, [2, 3]], + [friendsEntry2, [3, 3]]]), + ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?active}]), + s([{[friendsEntry2, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]), + + p("Adding two rows in subagent table with special INDEX (2)"), + s([{[kompissEntry2, [1, 3]], s, "kompis3"}, + {[kompissEntry2, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?createAndGo}]), + g([[kompissEntry2, [1, 3]], + [kompissEntry2, [2, 3]]]), + ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + gn([[kompissEntry2, [1]], + [kompissEntry2, [2]]]), + ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + s([{[kompissEntry2, [1, 2]], s, "kompis3"}, + {[kompissEntry2, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?createAndGo}]), + gn([[kompissEntry2, [1, 1]], + [kompissEntry2, [2, 1]]]), + ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?active}]), + s([{[kompissEntry2, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]), + s([{[kompissEntry2, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]), + ok. + +%% Req. Test1 +multi_threaded_test() -> + p("Testing multi threaded agent..."), + g([[multiStr,0]]), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(1, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "pelle"}]), + ?line expect(2, [{[sysLocation, 0], "pelle"}]), + Pid ! continue, + ?line expect(3, [{[multiStr,0], "ok"}]), + + s([{[multiStr, 0], s, "block"}]), + Pid2 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(4, [{[sysUpTime,0], any}]), + g([[multiStr,0]]), + Pid3 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(5, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "kalle"}]), + Pid3 ! continue, + ?line expect(6, [{[multiStr,0], "ok"}]), + Pid2 ! continue, + ?line expect(7, [{[multiStr,0], "block"}]), + ?line expect(8, [{[sysLocation,0], "kalle"}]). + +%% Req. Test1, TestTrapv2 +mt_trap_test(MA) -> + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + snmpa:send_trap(MA, mtTrap, "standard trap"), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(2, [{[sysUpTime,0], any}]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + Pid ! continue, + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [2]}, + {[multiStr,0], "ok"}]). + + +get_multi_pid() -> + get_multi_pid(10). +get_multi_pid(0) -> + ?line ?FAIL(no_global_name); +get_multi_pid(N) -> + sleep(1000), + case global:whereis_name(snmp_multi_tester) of + Pid when pid(Pid) -> Pid; + _ -> get_multi_pid(N-1) + end. + +%% Req. Test1 +types_v2_test() -> + p("Testing v2 types..."), + + s([{[bits1,0], 2#10}]), + ?line expect(1, [{[bits1,0], ?str(2#10)}]), + g([[bits1,0]]), + ?line expect(2, [{[bits1,0], ?str(2#101)}]), + + s([{[bits2,0], 2#11000000110}]), + ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]), + g([[bits2,0]]), + ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]), + + g([[bits3,0]]), + ?line expect(50, genErr, 1, any), + + g([[bits4,0]]), + ?line expect(51, genErr, 1, any), + + s([{[bits1,0], s, [2#10]}]), + ?line expect(6, ?v1_2(badValue, wrongValue), 1, any), + + s([{[bits2,0], 2#11001001101010011}]), + ?line expect(7, ?v1_2(badValue, wrongValue), 1, any). + + +%% Req. Test1 +implied_test(MA) -> + ?LOG("implied_test -> start",[]), + p("Testing IMPLIED..."), + + snmpa:verbosity(MA,trace), + snmpa:verbosity(MA,trace), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = "apa", + Idx2 = "qq", + ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]), + ?line expect(1, [{[testStatus, Idx1], ?createAndGo}, + {[testDescr, Idx1], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]), + ?line expect(2, [{[testStatus, Idx2], ?createAndGo}, + {[testDescr, Idx2], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr)",[]), + gn([[testDescr]]), + ?line expect(3, [{[testDescr,Idx1], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr) of row 1",[]), + gn([[testDescr,Idx1]]), + ?line expect(4, [{[testDescr,Idx2], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?destroy}]), + ?line expect(5, [{[testStatus, Idx1], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?destroy}]), + ?line expect(6, [{[testStatus, Idx2], ?destroy}]), + + %% Try the same in other table + Idx3 = [1, "apa"], + Idx4 = [1, "qq"], + ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]), + ?line expect(1, [{[testStatus2, Idx3], ?createAndGo}, + {[testDescr2, Idx3], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]), + ?line expect(2, [{[testStatus2, Idx4], ?createAndGo}, + {[testDescr2, Idx4], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr2)",[]), + gn([[testDescr2]]), + ?line expect(3, [{[testDescr2,Idx3], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr2) of row 1",[]), + gn([[testDescr2,Idx3]]), + ?line expect(4, [{[testDescr2,Idx4], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?destroy}]), + ?line expect(5, [{[testStatus2, Idx3], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?destroy}]), + ?line expect(6, [{[testStatus2, Idx4], ?destroy}]), + + snmpa:verbosity(MA,log), + + ?LOG("implied_test -> done",[]). + + + +%% Req. Test1 +sparse_table_test() -> + p("Testing sparse table..."), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + s([{[sparseStatus, Idx1], i, ?createAndGo}, + {[sparseDescr, Idx1], s, "row 1"}]), + ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo}, + {[sparseDescr, Idx1], "row 1"}]), + s([{[sparseStatus, Idx2], i, ?createAndGo}, + {[sparseDescr, Idx2], s, "row 2"}]), + ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo}, + {[sparseDescr, Idx2], "row 2"}]), + ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2], + [sparseStatus,Idx1], [sparseStatus,Idx2]]), + gb(0,5,[[sparseIndex]])), + ?line expect(3, [{[sparseDescr,Idx1], "row 1"}, + {[sparseDescr,Idx2], "row 2"}, + {[sparseStatus,Idx1], ?active}, + {[sparseStatus,Idx2], ?active}, + {[sparseStr,0], "slut"}]), + % Delete the rows + s([{[sparseStatus, Idx1], i, ?destroy}]), + ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]), + s([{[sparseStatus, Idx2], i, ?destroy}]), + ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]). + + +%% Req. Test1 +cnt_64_test(MA) -> + ?LOG("start cnt64 test (~p)",[MA]), + snmpa:verbosity(MA,trace), + ?LOG("start cnt64 test",[]), + p("Testing Counter64, and at the same time, RowStatus is not last column"), + + ?DBG("get cnt64",[]), + g([[cnt64,0]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(1, noSuchName, 1, any), + expect(1, [{[cnt64,0],18446744073709551615}])), + ?DBG("get-next cnt64",[]), + gn([[cnt64]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]), + expect(2, [{[cnt64,0],18446744073709551615}])), + ?DBG("send cntTrap",[]), + snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"}, + {cnt64, 10}, + {sysLocation, "here"}]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"}, + {[sysLocation,0], "here"}]), + expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [1]}, + {[sysContact,0], "pelle"}, + {[cnt64,0], 10}, + {[sysLocation,0], "here"}])), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + ?DBG("create row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]), + ?DBG("create row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]), + + ?DBG("get-next (cntIndex)",[]), + gn([[cntIndex]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]), + expect(3, [{[cntCnt,Idx1], 0}])), + % Delete the rows + ?DBG("delete row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(4, [{[cntStatus, Idx1], ?destroy}]), + ?DBG("delete row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(5, [{[cntStatus, Idx2], ?destroy}]), + catch snmpa:verbosity(MA,log), + ?DBG("done",[]), + ok. + +%% Req. Test1 +opaque_test() -> + p("Testing Opaque datatype..."), + g([[opaqueObj,0]]), + ?line expect(1, [{[opaqueObj,0], "opaque-data"}]). + +%% Req. OLD-SNMPEA-MIB +api_test(MaNode) -> + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [intAgentIpAddress]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, + oid_to_name, [OID]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [[1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, + int_to_enum, ['RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]), + ?line case snmp:date_and_time() of + List when list(List), length(List) == 8 -> ok; + List when list(List), length(List) == 11 -> ok + end. + +%% Req. Klas3 +api_test2() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]), + g([[fname4,0]]), + ?line expect(2, [{[fname4,0], 1}]). + +api_test3() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]). + + +unreg_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[snmpInPkts, 0], any}]). + +load_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[fname,0], ""}]). + +%% Req. Klas1 +load_test_sa() -> + gn([[?v1_2(sysServices,sysORLastChange), 0]]), + ?line expect(1, [{[fname,0], any}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_get() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0], Key1c4, [fname,0],Key1c3, + [sysName,0]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,0], "test"}]), + g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]), + ?line ?v1_2(expect(2, noSuchName, [1,4], any), + expect(2, [{[1,3,7,1], noSuchObject}, + {Key1c4, 2}, + {[sysDescr,0], "Erlang SNMP agent"}, + {[1,3,7,2], noSuchObject}, + {Key1c3, 2}, + {[sysDescr,0], "Erlang SNMP agent"}])). + +%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3. +do_mul_get_err() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]), + ?line ?v1_2(expect(1, noSuchName, 5, any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,2], noSuchInstance}])), + g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname3,0], noSuchObject}, + {Key1c3, 2}, + {[sysName,1], noSuchInstance}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, {[fname,0], "test set"}, + {Key1c3, 2}, {[sysName,0], "test"}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next_err() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[1,3,6,999], endOfMibView}, + {[fname,0], "test set"}, + {[1,3,90], endOfMibView}, + {Key1c3, 2}, + {[sysName,0], "test"}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set() -> + p("Adding one row in subagent table, and one in master table"), + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [sysLocation,0], + [friendsEntry, [3, 3]]]), + ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"}, + {[sysLocation,0], "new_value"}, + {[friendsEntry, [3, 3]], ?active}]), + g([NewKeyc4]), + ?line expect(3, [{NewKeyc4, 2}]), + s([{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]), + ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + p("Adding one row in subagent table, and one in master table"), + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {NewKeyc3, 2}, + {[sysUpTime,0], 45}, % sysUpTime (readOnly) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any), + g([[friendsEntry, [2, 3]]]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])), + g([NewKeyc4]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB +sa_mib() -> + g([[sa, [2,0]]]), + ?line expect(1, [{[sa, [2,0]], 3}]), + s([{[sa, [1,0]], s, "sa_test"}]), + ?line expect(2, [{[sa, [1,0]], "sa_test"}]). + +ma_trap1(MA) -> + snmpa:send_trap(MA, testTrap2, "standard trap"), + ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]), + snmpa:send_trap(MA, testTrap1, "standard trap"), + ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]). + +ma_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap2(MA) -> + snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1}, + {ifAdminStatus, [1], 1}, + {ifOperStatus, [1], 2}]), + ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}]). + +sa_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]], + "pelle"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}]). + +ma_v2_trap1(MA) -> + ?DBG("ma_v2_traps -> entry with MA = ~p => " + "send standard trap: testTrapv22",[MA]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]), + snmpa:send_trap(MA, testTrapv21, "standard trap"), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmp ++ [1]}]). + +ma_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}]). + +%% Note: This test case takes a while... actually a couple of minutes. +ma_v2_inform1(MA) -> + ?DBG("ma_v2_inform -> entry with MA = ~p => " + "send notification: testTrapv22",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag1, self()}, + "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag1, [_]} -> + ok; + {snmp_targets, tag1, Addrs1} -> + ?line ?FAIL({bad_addrs, Addrs1}) + after + 5000 -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag1, {got_response, _}} -> + ok; + {snmp_notification, tag1, {no_response, _}} -> + ?line ?FAIL(no_response) + after + 20000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + + %% + %% -- The rest is possibly erroneous... + %% + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag2, self()}, + "standard inform", []), + ?line expect(2, {inform, false}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag2, [_]} -> + ok; + {snmp_targets, tag2, Addrs2} -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]), + ?line ?FAIL({bad_addrs, Addrs2}) + after + 5000 -> + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag2, {got_response, _}} -> + ?line ?FAIL(got_response); + {snmp_notification, tag2, {no_response, _}} -> + ok + after + 240000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag2) timeout",[]), + ?line ?FAIL(nothing_at_all) + end. + + +ma_v1_2_v2_trap(MA) -> + snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmpTraps ++ [3]}, + {[ifIndex, 1], 1}, + {[snmpTrapEnterprise, 0], [1,2,3]}]). + + +ma_v1_2_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}, + {[snmpTrapEnterprise, 0], ?system}]). + + +sa_v1_2_v2_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + +sa_v1_2_v2_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], "pelle"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +sa_v1_2_v2_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 2]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_bad_value() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2}, + {[sa, [2,0]], 5}, % badValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, badValue, 2, any), + s([{NewKeyc3, 2}, + {[sa, [2,0]], 6}, % wrongValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, ?v1_2(badValue, wrongValue), 2, any), + g([NewKeyc4]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_gen_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2},{NewKeyc4, 2}, + {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]), + ?line expect(1, genErr, 4, any), +% The row might have been added; we don't know. +% (as a matter of fact we do - it is added, because the agent +% first sets its own vars, and then th SAs. Lets destroy it. + s([{NewKeyc5, ?destroy}]), + ?line expect(2, [{NewKeyc5, ?destroy}]). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_too_big() -> + g([[sa, [4,0]]]), + ?line expect(1, tooBig). + +%% Req. Klas1, system group, snmp group (v1/v2) +next_across_sa() -> + gn([[sysDescr],[klas1,5]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {[snmpInPkts, 0], any}]). + +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2} +%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2} +%% Req. Klas3, Klas4 +undo_test() -> + s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]), + ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any), + s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]), + ?line expect(3, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]), + ?line expect(4, ?v1_2(genErr, commitFailed), 1, any), +% unfortunatly we don't know if we'll get undoFailed or commitFailed. +% it depends on which order the agent traverses the varbind list. +% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]), +% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]), + ?line expect(6, genErr, 2, any). + +%% Req. Klas3, Klas4 +bad_return() -> + g([[fStatus4,4], + [fName4,4]]), + ?line expect(4, genErr, 2, any), + g([[fStatus4,5], + [fName4,5]]), + ?line expect(5, genErr, 1, any), + g([[fStatus4,6], + [fName4,6]]), + ?line expect(6, genErr, 2, any), + gn([[fStatus4,7], + [fName4,7]]), + ?line expect(7, genErr, 2, any), + gn([[fStatus4,8], + [fName4,8]]), + ?line expect(8, genErr, 1, any), + gn([[fStatus4,9], + [fName4,9]]), + ?line expect(9, genErr, 2, any). + + +%%%----------------------------------------------------------------- +%%% Test the implementation of standard mibs. +%%% We should *at least* try to GET all variables, just to make +%%% sure the instrumentation functions work. +%%% Note that many of the functions in the standard mib is +%%% already tested by the normal tests. +%%%----------------------------------------------------------------- +standard_mibs(suite) -> + [snmp_standard_mib, snmp_community_mib, + snmp_framework_mib, + snmp_target_mib, snmp_notification_mib, + snmp_view_based_acm_mib]. + +standard_mibs_2(suite) -> + [snmpv2_mib_2, snmp_community_mib_2, + snmp_framework_mib_2, + snmp_target_mib_2, snmp_notification_mib_2, + snmp_view_based_acm_mib_2]. + +standard_mibs_3(suite) -> + [snmpv2_mib_3,snmp_framework_mib_3, snmp_mpd_mib_3, + snmp_target_mib_3, snmp_notification_mib_3, + snmp_view_based_acm_mib_3, snmp_user_based_sm_mib_3]. + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v1. +%% o Test the counters and control objects in SNMP-STANDARD-MIB +%%----------------------------------------------------------------- +snmp_standard_mib(suite) -> []; +snmp_standard_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?DBG("snmp_standard_mib -> std_mib_init", []), + try_test(std_mib_init), + + ?DBG("snmp_standard_mib -> std_mib_a", []), + InBadVsns = try_test(std_mib_a), + put(vsn, v2), + ?DBG("snmp_standard_mib -> std_mib_read", []), + try_test(std_mib_read), + put(vsn, v1), + + ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]), + Bad = try_test(std_mib_b, [InBadVsns]), + ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []), + try_test(std_mib_read, [], [{community, "bad community"}]), + ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []), + try_test(std_mib_write, [], [{community, "public"}]), + ?DBG("snmp_standard_mib -> std_mib_asn_err", []), + try_test(std_mib_asn_err), + ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]), + try_test(std_mib_c, [Bad]), + ?DBG("snmp_standard_mib -> std_mib_a", []), + try_test(standard_mib_a), + + ?DBG("snmp_standard_mib -> std_mib_finish", []), + try_test(std_mib_finish), + ?DBG("snmp_standard_mib -> std_mib_test_finish", []), + try_test(standard_mib_test_finish, [], [{community, "bad community"}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_a() -> + ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]), + ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]), + ?line OutPkts2 = OutPkts + 1, + %% There are some more counters we could test here, but it's not that + %% important, since they are removed from SNMPv2-MIB. + ok. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_init() -> + %% disable authentication failure traps. (otherwise w'd get many of + %% them - this is also a test to see that it works). + s([{[snmpEnableAuthenTraps,0], 2}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_finish() -> + %% enable again + s([{[snmpEnableAuthenTraps,0], 1}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_test_finish() -> + %% force a authenticationFailure + std_mib_write(), + %% check that we got a trap + ?line expect(2, trap, [1,2,3], 4, 0, []). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_read() -> + ?DBG("std_mib_read -> entry", []), + g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply + ?DBG("std_mib_read -> await timeout (i.e. no reply)", []), + ?line expect(1, timeout). % make sure we don't get a trap! + + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_write() -> + ?DBG("std_mib_write -> entry", []), + s([{[sysLocation, 0], "new_value"}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_asn_err() -> + snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]). + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v2 and v3. +%% o Test the counters and control objects in SNMPv2-MIB +%%----------------------------------------------------------------- +snmpv2_mib_2(suite) -> []; +snmpv2_mib_2(Config) when list(Config) -> + ?LOG("snmpv2_mib_2 -> start",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?DBG("snmpv2_mib_2 -> standard mib init",[]), + try_test(std_mib_init), + + ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]), + InBadVsns = try_test(std_mib_a), + + ?DBG("snmpv2_mib_2 -> make a bad version read",[]), + put(vsn, v1), + try_test(std_mib_read), + + ?DBG("snmpv2_mib_2 -> bad version read",[]), + put(vsn, v2), + Bad = try_test(std_mib_b, [InBadVsns]), + + ?DBG("snmpv2_mib_2 -> read with bad community",[]), + try_test(std_mib_read, [], [{community, "bad community"}]), + + ?DBG("snmpv2_mib_2 -> write with public community",[]), + try_test(std_mib_write, [], [{community, "public"}]), + + ?DBG("snmpv2_mib_2 -> asn err",[]), + try_test(std_mib_asn_err), + + ?DBG("snmpv2_mib_2 -> check counters",[]), + try_test(std_mib_c, [Bad]), + + ?DBG("snmpv2_mib_2 -> get som counters",[]), + try_test(snmpv2_mib_a), + + ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]), + try_test(std_mib_finish), + + ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, " + "then disable auth traps",[]), + try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]), + + ?LOG("snmpv2_mib_2 -> done",[]). + +%% Req. SNMPv2-MIB +snmpv2_mib_3(suite) -> []; +snmpv2_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + InBadVsns = try_test(std_mib_a), + put(vsn, v1), + try_test(std_mib_read), + put(vsn, v3), + _Bad = try_test(std_mib_b, [InBadVsns]), + try_test(snmpv2_mib_a), + + try_test(std_mib_finish). + +-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]). + +%% Req. SNMPv2-MIB +snmpv2_mib_test_finish() -> + %% force a authenticationFailure + ?DBG("ma_v2_inform -> write to std mib",[]), + std_mib_write(), + + %% check that we got a trap + ?DBG("ma_v2_inform -> await trap",[]), + ?line expect(2, v2trap, [{[sysUpTime,0], any}, + {[snmpTrapOID,0], ?authenticationFailure}]), + + %% and the the inform + ?DBG("ma_v2_inform -> await inform",[]), + ?line expect(2, {inform,true}, [{[sysUpTime,0], any}, + {[snmpTrapOID,0],?authenticationFailure}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_a() -> + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + + ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]), + InBadVsns. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_b(InBadVsns) -> + ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]), + ?line InBadVsns2 = InBadVsns + 1, + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] = + get_req(4, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + {InBadCommunityNames, InBadCommunityUses, InASNErrs}. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) -> + ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] = + get_req(1, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + ?line InBadCommunityNames2 = InBadCommunityNames + 1, + ?line InBadCommunityUses2 = InBadCommunityUses + 1, + ?line InASNErrs2 = InASNErrs + 1. + +%% Req. SNMPv2-MIB +snmpv2_mib_a() -> + ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]), + s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]), + ?line expect(3, [{[snmpSetSerialNo,0], SetSerial}, + {[sysLocation, 0], "val2"}]), + s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]), + ?line expect(4, inconsistentValue, 2, + [{[sysLocation, 0], "val3"}, + {[snmpSetSerialNo,0], SetSerial}]), + ?line ["val2"] = get_req(5, [[sysLocation,0]]). + + +%%----------------------------------------------------------------- +%% o Bad community uses/name is tested already +%% in SNMPv2-MIB and STANDARD-MIB. +%% o Test add/deletion of rows. +%%----------------------------------------------------------------- +snmp_community_mib(suite) -> []; +snmp_community_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + try_test(snmp_community_mib), + ?line unload_master("SNMP-COMMUNITY-MIB"). + +snmp_community_mib_2(X) -> snmp_community_mib(X). + +%% Req. SNMP-COMMUNITY-MIB +snmp_community_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o Test engine boots / time +%%----------------------------------------------------------------- +snmp_framework_mib(suite) -> []; +snmp_framework_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + try_test(snmp_framework_mib), + ?line unload_master("SNMP-FRAMEWORK-MIB"). + +snmp_framework_mib_2(X) -> snmp_framework_mib(X). + +snmp_framework_mib_3(suite) -> []; +snmp_framework_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(snmp_framework_mib). + + +%% Req. SNMP-FRAMEWORK-MIB +snmp_framework_mib() -> + ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]), + ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]), + sleep(5000), + ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]), + if + EngineTime+7 < EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + EngineTime+4 > EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + true -> ok + end, + ?line case get_req(4, [[snmpEngineBoots,0]]) of + [Boots] when integer(Boots) -> ok; + Else -> ?FAIL(Else) + end, + ok. + +%%----------------------------------------------------------------- +%% o Test the counters +%%----------------------------------------------------------------- +snmp_mpd_mib_3(suite) -> []; +snmp_mpd_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + UnknownPDUHs = try_test(snmp_mpd_mib_a), + try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]), + try_test(snmp_mpd_mib_c, [UnknownPDUHs]). + + +%% Req. SNMP-MPD-MIB +snmp_mpd_mib_a() -> + ?line [UnknownSecs, InvalidMsgs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0]]), + Pdu = #pdu{type = 'get-request', + request_id = 23, + error_status = noError, + error_index = 0, + varbinds = []}, + SPdu = #scopedPdu{contextEngineID = "agentEngine", + contextName = "", + data = Pdu}, + ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu), + V3Hdr1 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [7], + msgSecurityModel = 23, % bad sec model + msgSecurityParameters = []}, + V3Hdr2 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [6], % bad flag combination + msgSecurityModel = 3, + msgSecurityParameters = []}, + Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1, + data = SPDUBytes}, + Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2, + data = SPDUBytes}, + ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1), + ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2), + snmp_test_mgr:send_bytes(MsgBytes1), + snmp_test_mgr:send_bytes(MsgBytes2), + + ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0], + [snmpUnknownPDUHandlers, 0]]), + ?line UnknownSecs2 = UnknownSecs + 1, + ?line InvalidMsgs2 = InvalidMsgs + 1, + UnknownPDUHs. + +-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]). +snmp_mpd_mib_b() -> + g([[sysUpTime,0]]), + ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]). + + +snmp_mpd_mib_c(UnknownPDUHs) -> + ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]), + ?line UnknownPDUHs2 = UnknownPDUHs + 1. + + +snmp_target_mib(suite) -> []; +snmp_target_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-TARGET-MIB"), + try_test(snmp_target_mib), + ?line unload_master("SNMP-TARGET-MIB"). + +snmp_target_mib_2(X) -> snmp_target_mib(X). + +snmp_target_mib_3(X) -> snmp_target_mib(X). + +snmp_target_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +snmp_notification_mib(suite) -> []; +snmp_notification_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + try_test(snmp_notification_mib), + ?line unload_master("SNMP-NOTIFICATION-MIB"). + +snmp_notification_mib_2(X) -> snmp_notification_mib(X). + +snmp_notification_mib_3(X) -> snmp_notification_mib(X). + +snmp_notification_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o add/delete views and try them +%% o try boundaries +%%----------------------------------------------------------------- +snmp_view_based_acm_mib(suite) -> []; +snmp_view_based_acm_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master("Test2"), + snmp_view_based_acm_mib(), + ?line unload_master("Test2"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib() -> + snmpa:verbosity(net_if,trace), + snmpa:verbosity(master_agent,trace), + ?LOG("start snmp_view_based_acm_mib test",[]), + %% The user "no-rights" is present in USM, and is mapped to security + %% name 'no-rights", which is not present in VACM. + %% So, we'll add rights for it, try them and delete them. + %% We'll give "no-rights" write access to tDescr.0 and read access + %% to tDescr2.0 + %% These are the options we'll use to the mgr + Opts = [{user, "no-rights"}, {community, "no-rights"}], + %% Find the valid secmodel, and one invalid secmodel. + {SecMod, InvSecMod} = + case get(vsn) of + v1 -> {?SEC_V1, ?SEC_V2C}; + v2 -> {?SEC_V2C, ?SEC_USM}; + v3 -> {?SEC_USM, ?SEC_V1} + end, + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Now, add a mapping from "no-rights" -> "no-rights-group" + GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]], + GRow1 = + [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"}, + {GRow1Status, ?createAndGo}], + ?DBG("set '~p'",[GRow1]), + ?line try_test(do_set, [GRow1]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Create a mapping for another sec model, and make sure it dosn't + %% give us access + GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]], + GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"}, + {GRow2Status, ?createAndGo}], + + ?DBG("set '~p'",[GRow2]), + ?line try_test(do_set, [GRow2]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [GRow2Status]), + + RVName = "rv_name", + WVName = "wv_name", + + %% Access row + ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1], + ARow1Status = [vacmAccessStatus, ARow1Idx], + ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1}, + {[vacmAccessReadViewName, ARow1Idx], RVName}, + {[vacmAccessWriteViewName, ARow1Idx], WVName}, + {ARow1Status, ?createAndGo}], + + %% This access row would give acces, if InvSecMod was valid. + ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1], + ARow2Status = [vacmAccessStatus, ARow2Idx], + ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1}, + {[vacmAccessReadViewName, ARow2Idx], "internet"}, + {[vacmAccessWriteViewName, ARow2Idx], "internet"}, + {ARow2Status, ?createAndGo}], + + ?line try_test(do_set, [ARow2]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [ARow2Status]), + + + %% Add valid row + ?line try_test(do_set, [ARow1]), + + ?line try_test(use_no_rights, [], Opts), + + %% Create the view family + VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access + VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access + VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access + VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access + VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx], + VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx], + VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx], + VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx], + + ?line try_test(add_row, [VRow1Status]), + ?line try_test(add_row, [VRow2Status]), + ?line try_test(add_row, [VRow3Status]), + + %% We're supposed to have access now... + ?line try_test(use_rights, [], Opts), + + %% Change Row3 to Row4 + ?line try_test(del_row, [VRow3Status]), + ?line try_test(add_row, [VRow4Status]), + + %% We should still have access... + ?line try_test(use_rights, [], Opts), + + %% Delete rows + ?line try_test(del_row, [GRow1Status]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete rest of rows + ?line try_test(del_row, [ARow1Status]), + ?line try_test(del_row, [VRow1Status]), + ?line try_test(del_row, [VRow2Status]), + ?line try_test(del_row, [VRow4Status]), + + ?line try_test(use_no_rights, [], Opts), + snmpa:verbosity(master_agent,log). + +do_set(Row) -> + s(Row), + expect(1, Row). + +add_row(RowStatus) -> + s([{RowStatus, ?createAndGo}]), + expect(1, [{RowStatus, ?createAndGo}]). + +del_row(RowStatus) -> + s([{RowStatus, ?destroy}]), + expect(1, [{RowStatus, ?destroy}]). + + + +use_no_rights() -> + g([[xDescr,0]]), + ?v1_2_3(expect(11, noSuchName, 1, any), + expect(12, [{[xDescr,0], noSuchObject}]), + expect(13, authorizationError, 1, any)), + g([[xDescr2,0]]), + ?v1_2_3(expect(21, noSuchName, 1, any), + expect(22, [{[xDescr2,0], noSuchObject}]), + expect(23, authorizationError, 1, any)), + gn([[xDescr]]), + ?v1_2_3(expect(31, noSuchName, 1, any), + expect(32, [{[xDescr], endOfMibView}]), + expect(33, authorizationError, 1, any)), + s([{[xDescr,0], "tryit"}]), + ?v1_2_3(expect(41, noSuchName, 1, any), + expect(42, noAccess, 1, any), + expect(43, authorizationError, 1, any)). + + +use_rights() -> + g([[xDescr,0]]), + expect(1, [{[xDescr,0], any}]), + g([[xDescr2,0]]), + expect(2, [{[xDescr2,0], any}]), + s([{[xDescr,0], "tryit"}]), + expect(3, noError, 0, any), + g([[xDescr,0]]), + expect(4, [{[xDescr,0], "tryit"}]). + +mk_ln(X) -> + [length(X) | X]. + +%%----------------------------------------------------------------- +%% o add/delete users and try them +%% o test all secLevels +%% o test all combinations of protocols +%% o try bad ops; check counters +%%----------------------------------------------------------------- +snmp_user_based_sm_mib_3(suite) -> []; +snmp_user_based_sm_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + _AgentDir = ?config(agent_dir, Config), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + + %% The newUser used here already has VACM access. + + %% Add a new user in the simplest way; just createAndGo + try_test(v3_sync, [[{usm_add_user1, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new user + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"), + DesKey1 = lists:sublist(ShaKey1, 16), + + %% Change the new user's keys - 1 + try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + MgrDir = ?config(mgr_dir, Config), + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"), + DesKey2 = lists:sublist(ShaKey2, 16), + + %% Change the new user's keys - 2 + ?line try_test(v3_sync, + [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + reset_usm_mgr(MgrDir), + ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2), + ?line load_master("Test2"), + ?line try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Change the new user's keys - 3 + ?line try_test(v3_sync, + [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new keys + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Try some read requests + ?line try_test(v3_sync, [[{usm_read, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Delete the new user + ?line try_test(v3_sync, [[{usm_del_user, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try some bad requests + ?line try_test(v3_sync, [[{usm_bad, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("SNMP-USER-BASED-SM-MIB"). + +-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]). + +usm_add_user1() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +usm_use_user() -> + v2_proc(). + + +%% Change own public keys +usm_key_change1(ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_shaxxxxxxxxxx", + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_desxxxxxx", + DesKey), + Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change own private keys +usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change other's public keys +usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}], + s(Vbs1), + ?line expect(1, noAccess, 1, any), + Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs2), + ?line expect(2, noAccess, 1, any), + + + Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs3), + ?line expect(1, Vbs3). + +usm_read() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ?line g([[usmUserSecurityName, NewRowIndex], + [usmUserCloneFrom, NewRowIndex], + [usmUserAuthKeyChange, NewRowIndex], + [usmUserOwnAuthKeyChange, NewRowIndex], + [usmUserPrivKeyChange, NewRowIndex], + [usmUserOwnPrivKeyChange, NewRowIndex]]), + ?line expect(1, + [{[usmUserSecurityName, NewRowIndex], "newUser"}, + {[usmUserCloneFrom, NewRowIndex], [0,0]}, + {[usmUserAuthKeyChange, NewRowIndex], ""}, + {[usmUserOwnAuthKeyChange, NewRowIndex], ""}, + {[usmUserPrivKeyChange, NewRowIndex], ""}, + {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]), + ok. + + + +usm_del_user() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]). + +-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]). + +-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]). + +-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]). + +-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]). + +-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]). + +usm_bad() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, inconsistentName, 1, any), + + RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs2), + ?line expect(2, wrongValue, 1, any), + + RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs3), + ?line expect(3, Vbs3), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]), + ?line expect(4, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]), + ?line expect(5, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]), + ?line expect(6, wrongValue, 1, any), + ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]), + ?line expect(7, wrongValue, 1, any), + + Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs4), + ?line expect(1, Vbs4), + + ok. + + +%%----------------------------------------------------------------- +%% Loop through entire MIB, to make sure that all instrum. funcs +%% works. +%% Load all std mibs that are not loaded by default. +%%----------------------------------------------------------------- +loop_mib(suite) -> []; +loop_mib(Config) when list(Config) -> + ?LOG("loop_mib -> initiate case",[]), + %% snmpa:verbosity(master_agent,debug), + %% snmpa:verbosity(mib_server,info), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]), + ?line load_master_std("SNMP-MPD-MIB"), + ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?DBG("loop_mib -> try",[]), + try_test(loop_mib_1), + ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]), + ?line unload_master("SNMP-MPD-MIB"), + ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + %% snmpa:verbosity(master_agent,log), + %% snmpa:verbosity(mib_server,silence), + ?LOG("loop_mib -> done",[]). + + +loop_mib_2(suite) -> []; +loop_mib_2(Config) when list(Config) -> + ?LOG("loop_mib_2 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_2 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_2 -> load mibs",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_2 -> unload mibs",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?LOG("loop_mib_2 -> done",[]). + + +loop_mib_3(suite) -> []; +loop_mib_3(Config) when list(Config) -> + ?LOG("loop_mib_3 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_3 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_3 -> load mibs",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_3 -> unload mibs",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?LOG("loop_mib_3 -> done",[]). + + +%% Req. As many mibs all possible +loop_mib_1() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_1([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_1(Oid, N) -> + ?DBG("loop_it_1 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_1 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_1 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_1(NOid, N+1); + #pdu{type='get-response', error_status=noSuchName, error_index=1, + varbinds=[_]} -> + ?DBG("loop_it_1 -> done",[]), + N; + + #pdu{type = Type, error_status = Err, error_index = Idx, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs}) + end. + +%% Req. As many mibs all possible +loop_mib_2() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_2([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_2(Oid, N) -> + ?DBG("loop_it_2 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid, value = endOfMibView}]} -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p",[NOid]), + N; + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_2 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_2(NOid, N+1) + end. + + +%%%----------------------------------------------------------------- +%%% Testing of reported bugs and other tickets. +%%%----------------------------------------------------------------- + +reported_bugs(suite) -> + [otp_1128, otp_1129, otp_1131, otp_1162, + otp_1222, otp_1298, otp_1331, otp_1338, + otp_1342, otp_2776, otp_2979, otp_3187, otp_3725]. + +reported_bugs_2(suite) -> + [otp_1128_2, otp_1129_2, otp_1131_2, otp_1162_2, + otp_1222_2, otp_1298_2, otp_1331_2, otp_1338_2, + otp_1342_2, otp_2776_2, otp_2979_2, otp_3187_2]. + +reported_bugs_3(suite) -> + [otp_1128_3, otp_1129_3, otp_1131_3, otp_1162_3, + otp_1222_3, otp_1298_3, otp_1331_3, otp_1338_3, + otp_1342_3, otp_2776_3, otp_2979_3, otp_3187_3, + otp_3542]. + + +%% These are (ticket) test cases where the initiation has to be done +%% individually. +tickets(suite) -> + [otp_4394]. + +%%----------------------------------------------------------------- +%% Ticket: OTP-1128 +%% Slogan: Bug in handling of createAndWait set-requests. +%%----------------------------------------------------------------- +otp_1128(suite) -> []; +otp_1128(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1128), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1128_2(X) -> otp_1128(X). + +otp_1128_3(X) -> otp_1128(X). + +otp_1128() -> + io:format("Testing bug reported in ticket OTP-1128...~n"), + + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + + s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(29, [{NewKeyc5, ?notReady}]), + s([{NewKeyc5, ?active}, {NewKeyc3, 2}]), + ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(31, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(32, [{NewKeyc5, ?destroy}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1129, OTP-1169 +%% Slogan: snmpa:int_to_enum crashes on bad oids +%%----------------------------------------------------------------- +otp_1129(suite) -> []; +otp_1129(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + try_test(otp_1129_i, [node()]), + ?line unload_master("Klas3"). + +otp_1129_2(X) -> otp_1129(X). + +otp_1129_3(X) -> otp_1129(X). + +otp_1129_i(MaNode) -> + io:format("Testing bug reported in ticket OTP-1129...~n"), + false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]), + false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1131 +%% Slogan: Agent crashes / erlang node halts if RowIndex in a +%% setrequest is of bad type, e.g. an INDEX {INTEGER}, +%% and RowIdenx [3,2]. +%%----------------------------------------------------------------- +otp_1131(suite) -> []; +otp_1131(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas1"), + try_test(otp_1131), + ?line unload_master("Klas1"). + +otp_1131_2(X) -> otp_1131(X). + +otp_1131_3(X) -> otp_1131(X). + +otp_1131() -> + io:format("Testing bug reported in ticket OTP-1131...~n"), + s([{[friendsEntry, [2, 3, 1]], s, "kompis3"}, + {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1162 +%% Slogan: snmp_agent can't handle wrongValue from instrum.func +%%----------------------------------------------------------------- +otp_1162(suite) -> []; +otp_1162(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + try_test(otp_1162), + stop_subagent(SA). + +otp_1162_2(X) -> otp_1162(X). + +otp_1162_3(X) -> otp_1162(X). + +otp_1162() -> + s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok) + ?line expect(1, ?v1_2(badValue, wrongValue), 1, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1222 +%% Slogan: snmp agent crash if faulty index is returned from instrum +%%----------------------------------------------------------------- +otp_1222(suite) -> []; +otp_1222(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + ?line load_master("Klas4"), + try_test(otp_1222), + ?line unload_master("Klas3"), + ?line unload_master("Klas4"). + +otp_1222_2(X) -> otp_1222(X). + +otp_1222_3(X) -> otp_1222(X). + +otp_1222() -> + io:format("Testing bug reported in ticket OTP-1222...~n"), + s([{[fStatus4,1], 4}, {[fName4,1], 1}]), + ?line expect(1, genErr, 0, any), + s([{[fStatus4,2], 4}, {[fName4,2], 1}]), + ?line expect(2, genErr, 0, any). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1298 +%% Slogan: Negative INTEGER values are treated as positive. +%%----------------------------------------------------------------- +otp_1298(suite) -> []; +otp_1298(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1298), + ?line unload_master("Klas2"). + +otp_1298_2(X) -> otp_1298(X). + +otp_1298_3(X) -> otp_1298(X). + +otp_1298() -> + io:format("Testing bug reported in ticket OTP-1298...~n"), + s([{[fint,0], -1}]), + ?line expect(1298, [{[fint,0], -1}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1331 +%% Slogan: snmp_generic should return noError when deleting non-ex row +%%----------------------------------------------------------------- +otp_1331(suite) -> []; +otp_1331(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1331), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1331_2(X) -> otp_1331(X). + +otp_1331_3(X) -> otp_1331(X). + +otp_1331() -> + NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")], + s([{NewKeyc5, ?destroy}]), + ?line expect(1, [{NewKeyc5, ?destroy}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1338 +%% Slogan: snmp bug in initialisation of default values for mnesia tabs +%%----------------------------------------------------------------- +otp_1338(suite) -> []; +otp_1338(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1338), + ?line unload_master("Klas2"). + +otp_1338_2(X) -> otp_1338(X). + +otp_1338_3(X) -> otp_1338(X). + +otp_1338() -> + s([{[kStatus2, 7], i, ?createAndGo}]), + ?line expect(1, [{[kStatus2, 7], ?createAndGo}]), + g([[kName2, 7]]), + ?line expect(2, [{[kName2, 7], "JJJ"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1342 +%% Slogan: default impl of snmp table can't handle bad index access, +%% Set when INDEX is read-write gets into an infinite loop! +%%----------------------------------------------------------------- +otp_1342(suite) -> []; +otp_1342(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas4"), + try_test(otp_1342), + ?line unload_master("Klas4"). + +otp_1342_2(X) -> otp_1342(X). + +otp_1342_3(X) -> otp_1342(X). + +otp_1342() -> + s([{[fIndex5, 1], i, 1}, + {[fName5, 1], i, 3}, + {[fStatus5, 1], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1366 +%% Slogan: snmp traps not sent to all managers +%% Note: NYI! We need a way to tell the test server that we need +%% mgrs on two different machines. +%%----------------------------------------------------------------- +otp_1366(suite) -> []; +otp_1366(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1366), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1366_2(X) -> otp_1366(X). + +otp_1366_3(X) -> otp_1366(X). + +otp_1366() -> + ?INF("NOT YET IMPLEMENTED", []), + 'NYI'. + +%%----------------------------------------------------------------- +%% Ticket: OTP-2776 +%% Slogan: snmp:validate_date_and_time() fails when time is 00:00 +%%----------------------------------------------------------------- +otp_2776(suite) -> []; +otp_2776(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_2776). + +otp_2776_2(X) -> otp_2776(X). + +otp_2776_3(X) -> otp_2776(X). + +otp_2776() -> + io:format("Testing bug reported in ticket OTP-2776...~n"), + + Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0], + Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00 + Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0], + Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0], + Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0], + Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0], + Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2 + Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0], + Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4 + Dt10_invalid = [], + Dt11_invalid = [kalle,hobbe], + L = [{ 1, true, Dt01_valid}, + { 2, true, Dt02_valid}, + { 3, true, Dt03_valid}, + { 4, false, Dt04_invalid}, + { 5, true, Dt05_valid}, + { 6, true, Dt06_valid}, + { 7, false, Dt07_invalid}, + { 8, true, Dt08_valid}, + { 9, false, Dt09_invalid}, + {10, false, Dt10_invalid}, + {11, false, Dt11_invalid}], + + ?line ok = validate_dat(L). + + +validate_dat(L) -> validate_dat(L,[]). + +validate_dat([],V) -> + Fun = fun({_,X}) -> case X of + ok -> false; + _ -> true + end + end, + validate_dat1( lists:reverse( lists:filter(Fun,V) ) ); +validate_dat([{Id,E,Dat}|T],V) -> + validate_dat(T,[validate_dat2(Id,E,Dat) | V]). + +validate_dat1([]) -> ok; +validate_dat1(L) -> {error,L}. + +validate_dat2(Id, E, Dat) -> + Res = case {E,snmp:validate_date_and_time(Dat)} of + {E,E} -> ok; + {E,A} -> {E,A} + end, + {Id, Res}. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-2979 +%% Slogan: get-next on more than 1 column in an empty table +%% returns bad response. +%%----------------------------------------------------------------- +otp_2979(suite) -> []; +otp_2979(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Test1"), + ?line init_old(), + try_test(otp_2979), + ?line unload_master("Test1"). + +otp_2979_2(X) -> otp_2979(X). + +otp_2979_3(X) -> otp_2979(X). + +otp_2979() -> + gn([[sparseDescr], [sparseStatus]]), + ?line expect(1, [{[sparseStr,0], "slut"}, + {[sparseStr,0], "slut"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3187 +%% Slogan: get-next on vacmAccessTable for colums > 5 returns +%% endOfTable - should return value. +%%----------------------------------------------------------------- +otp_3187(suite) -> []; +otp_3187(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + otp_3187(), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +otp_3187_2(X) -> otp_3187(X). + +otp_3187_3(X) -> otp_3187(X). + +otp_3187() -> + ?line Elements = + snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]), + lists:foreach(fun(E) -> + ?line if E == endOfTable -> + ?FAIL(endOfTable); + true -> ok + end + end, Elements). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3542 +%% Slogan: +%%----------------------------------------------------------------- +otp_3542(suite) -> []; +otp_3542(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_3542). + +otp_3542() -> + io:format("SNMP v3 discovery...~n"), + ?line Res = snmp_test_mgr:d(), + io:format("SNMP v3 discovery result: ~p~n",[Res]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-3725 +%% Slogan: Slow response time on snmpa:int_to_enum +%%----------------------------------------------------------------- +otp_3725(suite) -> []; +otp_3725(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_3725_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +%% Req. OLD-SNMPEA-MIB +otp_3725_test(MaNode) -> + io:format("Testing feature requested in ticket OTP-3725...~n"), + ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]), + ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]), + ?DBG("otp_3725_test -> Db = ~p",[Db]), + + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [Db, intAgentIpAddress]), + ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name, + [Db,OID]), + ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [Db, [1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [Db, intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum, + [Db, 'RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]), + ok. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-4394 +%% Slogan: Target mib tag list check invalid +%%----------------------------------------------------------------- + + +otp_4394(suite) -> {req, [], {conf, + init_otp_4394, + [otp_4394_test], + finish_otp_4394}}. + +init_otp_4394(Config) when list(Config) -> + ?DBG("init_otp_4394 -> entry with" + "~n Config: ~p", [Config]), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line otp_4394_config(AgentDir, MgrDir, Ip), + MasterAgentVerbosity = {master_agent_verbosity, trace}, + NetIfVerbosity = {net_if_verbosity, trace}, + Opts = [MasterAgentVerbosity,NetIfVerbosity], + [{vsn, v1} | start_v1_agent(Config,Opts)]. + +otp_4394_config(AgentDir, MgrDir, Ip0) -> + ?DBG("otp_4394_config -> entry with" + "~n AgentDir: ~p" + "~n MgrDir: ~p" + "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]), + Vsn = [v1], + Ip = tuple_to_list(Ip0), + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip, + ?TRAP_UDP, Ip, 4000, + "OTP-4394 test"), + ?line case update_usm(Vsn, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsn, MgrDir); + false -> + ?line ok + end, + C1 = {"a", "all-rights", "initial", "", "pc"}, + C2 = {"c", "secret", "secret_name", "", "secret_tag"}, + ?line write_community_conf(AgentDir, [C1, C2]), + ?line update_vacm(Vsn, AgentDir), + Ta1 = {"shelob v1", + [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda + "pc1", + "target_v1", "", + %% [255,255,255,255,0,0], + [], + 2048}, + Ta2 = {"bifur v1", + [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip + "pc2", + "target_v1", "", + %% [255,255,255,255,0,0], + [], 2048}, + ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]), + ?line write_target_params_conf(AgentDir, Vsn), + ?line write_notify_conf(AgentDir), + ok. + + + +finish_otp_4394(Config) when list(Config) -> + ?DBG("finish_otp_4394 -> entry", []), + C1 = stop_agent(Config), + delete_files(C1), + erase(mgr_node), + lists:keydelete(vsn, 1, C1). + +otp_4394_test(suite) -> []; +otp_4394_test(Config) -> + ?DBG("otp_4394_test -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_4394_test1), + ?DBG("otp_4394_test -> done", []), + ok. + +otp_4394_test1() -> + ?DBG("otp_4394_test1 -> entry", []), + gn([[1,1]]), + Res = + case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of + %% {error, 1, {"?",[]}, {"~w",[timeout]}} + {error, 1, _, {_, [timeout]}} -> + ?DBG("otp_4394_test1 -> expected result: timeout", []), + ok; + Else -> + Else + end, + ?DBG("otp_4394_test1 -> done with: ~p", [Res]), + Res. + + +%%%-------------------------------------------------- +%%% Used to test the standard mib with our +%%% configuration. +%%%-------------------------------------------------- +run(F, A, Opts) -> + M = get(mib_dir), + Dir = get(mgr_dir), + User = snmp_misc:get_option(user, Opts, "all-rights"), + SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv), + EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"), + CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID), + Community = snmp_misc:get_option(community, Opts, "all-rights"), + ?DBG("run -> start crypto app",[]), + Crypto = case os:type() of + vxworks -> + no_crypto; + _ -> + ?CRYPTO_START() + end, + ?DBG("run -> Crypto: ~p",[Crypto]), + catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + ?DBG("run -> config:~n" + "\tM: ~p~n" + "\tDir: ~p~n" + "\tUser: ~p~n" + "\tSecLevel: ~p~n" + "\tEngineID: ~p~n" + "\tCtxEngineID: ~p~n" + "\tCommunity: ~p~n" + "\tStdM: ~p", + [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]), + case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()}, + {packet_server_debug,true}, + {debug,true}, + {agent, get(master_host)}, + {agent_udp, 4000}, + {trap_udp, 5000}, + {recbuf,65535}, + quiet, + get(vsn), + {community, Community}, + {user, User}, + {sec_level, SecLevel}, + {engine_id, EngineID}, + {context_engine_id, CtxEngineID}, + {dir, Dir}, + {mibs, mibs(StdM, M)}]) of + {ok, _Pid} -> + Res = apply(?MODULE, F, A), + catch snmp_test_mgr:stop(), + Res; + Err -> + io:format("Error starting manager: ~p\n", [Err]), + catch snmp_test_mgr:stop(), + ?line exit({mgr_start, Err}) + end. + + +mibs(StdMibDir,MibDir) -> + [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")), + join(MibDir, "OLD-SNMPEA-MIB.bin"), + join(StdMibDir, "SNMP-FRAMEWORK-MIB"), + join(StdMibDir, "SNMP-MPD-MIB"), + join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"), + join(StdMibDir, "SNMP-USER-BASED-SM-MIB"), + join(StdMibDir, "SNMP-TARGET-MIB"), + join(StdMibDir, "SNMP-NOTIFICATION-MIB"), + join(MibDir, "Klas1.bin"), + join(MibDir, "Klas2.bin"), + join(MibDir, "Klas3.bin"), + join(MibDir, "Klas4.bin"), + join(MibDir, "SA-MIB.bin"), + join(MibDir, "TestTrap.bin"), + join(MibDir, "Test1.bin"), + join(MibDir, "Test2.bin"), + join(MibDir, "TestTrapv2.bin")]. + +join(D,F) -> + filename:join(D,F). + +%% string used in index +is(S) -> [length(S) | S]. + +try_test(Func) -> + call(get(mgr_node), ?MODULE, run, [Func, [], []]). + +try_test(Func, A) -> + call(get(mgr_node), ?MODULE, run, [Func, A, []]). + +try_test(Func, A, Opts) -> + call(get(mgr_node), ?MODULE, run, [Func, A, Opts]). + +call(N,M,F,A) -> + ?DBG("call -> entry with~n" + " N: ~p~n" + " M: ~p~n" + " F: ~p~n" + " A: ~p~n" + " when~n" + " get(): ~p", + [N,M,F,A,get()]), + spawn(N, ?MODULE, wait, [self(),get(),M,F,A]), + receive + {done, {'EXIT', Rn}, Loc} -> + ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]), + put(test_server_loc, Loc), + exit(Rn); + {done, Ret, Zed} -> + ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]), + Ret + end. + +wait(From, Env, M, F, A) -> + ?DBG("wait -> entry with ~n" + "\tFrom: ~p~n" + "\tEnv: ~p",[From,Env]), + lists:foreach(fun({K,V}) -> put(K,V) end, Env), + Rn = (catch apply(M, F, A)), + ?DBG("wait -> Rn: ~n~p", [Rn]), + From ! {done, Rn, get(test_server_loc)}, + exit(Rn). + +expect(A,B) -> ok = snmp_test_mgr:expect(A,B). +expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C). +expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D). +expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F). + +get_req(Id, Vars) -> + ?DBG("get_req -> entry with~n" + "\tId: ~p~n" + "\tVars: ~p",[Id,Vars]), + g(Vars), + ?DBG("get_req -> await response",[]), + {ok, Val} = snmp_test_mgr:get_response(Id, Vars), + ?DBG("get_req -> response: ~p",[Val]), + Val. + +get_next_req(Vars) -> + ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]), + gn(Vars), + ?DBG("get_next_req -> await response",[]), + Response = snmp_test_mgr:receive_response(), + ?DBG("get_next_req -> response: ~p",[Response]), + Response. + + + +start_node(Name) -> + ?LOG("start_node -> entry with Name: ~p",[Name]), + M = list_to_atom(?HOSTNAME(node())), + ?DBG("start_node -> M: ~p",[M]), + Pa = filename:dirname(code:which(?MODULE)), + ?DBG("start_node -> Pa: ~p",[Pa]), + + Args = case init:get_argument('CC_TEST') of + {ok, [[]]} -> + " -pa /clearcase/otp/libraries/snmp/ebin "; + {ok, [[Path]]} -> + " -pa " ++ Path; + error -> + "" + end, + %% Do not use start_link!!! (the proc that calls this one is tmp) + ?DBG("start_node -> Args: ~p~n",[Args]), + A = Args ++ " -pa " ++ Pa, + case (catch ?START_NODE(Name, A)) of + {ok, Node} -> + %% Tell the test_server to not clean up things it never started. + ?DBG("start_node -> Node: ~p",[Node]), + {ok, Node}; + Else -> + ?ERR("start_node -> failed with(other): Else: ~p",[Else]), + ?line ?FAIL(Else) + end. + + +stop_node(Node) -> + ?LOG("stop_node -> Node: ~p",[Node]), + rpc:cast(Node, erlang, halt, []). + +p(X) -> + io:format(user, X++"\n", []). + +sleep(X) -> + receive + after + X -> ok + end. + +%%%----------------------------------------------------------------- +%%% Configuration +%%%----------------------------------------------------------------- +config(Vsns, MgrDir, AgentDir, MIp, AIp) -> + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp, + ?TRAP_UDP, AIp, 4000, + "test"), + ?line case update_usm(Vsns, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsns, MgrDir); + false -> + ?line ok + end, + ?line update_community(Vsns, AgentDir), + ?line update_vacm(Vsns, AgentDir), + ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns), + ?line write_target_params_conf(AgentDir, Vsns), + ?line write_notify_conf(AgentDir), + ok. + +delete_files(Config) -> + Dir = ?config(agent_dir, Config), + {ok, List} = file:list_dir(Dir), + lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end, + List). + +update_usm(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +update_usm_mgr(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +rewrite_usm_mgr(Dir, ShaKey, DesKey) -> + ?line ok = file:rename(filename:join(Dir,"usm.conf"), + filename:join(Dir,"usm.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + file:close(Fid). + +reset_usm_mgr(Dir) -> + ?line ok = file:rename(filename:join(Dir,"usm.old"), + filename:join(Dir,"usm.conf")). + + +update_community([v3], _Dir) -> ok; +update_community(_, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n", + []), + file:close(Fid). + + +-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]). +update_vacm(_Vsn, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]), + ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", " + "~w, excluded, null}.\n", [?tDescr_instance]), + file:close(Fid). + + +vacm_ver(v1) -> v1; +vacm_ver(v2) -> v2c; +vacm_ver(v3) -> usm. + + +write_community_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write), + ok = write_community_conf1(Fid, Confs), + file:close(Fid). + +write_community_conf1(_, []) -> + ok; +write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) -> + ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n", + [ComIdx, ComName, SecName, CtxName, TransTag]), + write_community_conf1(Fid, Confs). + + +write_target_addr_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + ok = write_target_addr_conf1(Fid, Confs), + file:close(Fid). + + +write_target_addr_conf1(_, []) -> + ok; +write_target_addr_conf1(Fid, + [{Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz}|Confs]) -> + ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", + [Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz]), + write_target_addr_conf1(Fid, Confs). + +write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + lists:foreach(fun(Vsn) -> + ok = io:format(Fid, + "{\"~s\", ~w, ~w, 1500, 3, " + "\"std_trap\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, mk_param(Vsn)]), + case Vsn of + v1 -> ok; + v2 -> + ok = io:format(Fid, + "{\"~s.2\",~w,~w,1500,3, " + "\"std_inform\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]); + v3 -> + ok = io:format(Fid, + "{\"~s.3\",~w,~w,1500,3, " + "\"std_inform\", \"~s\", " + "\"mgrEngine\", [], 1024}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]) + end + end, + Vsns), + file:close(Fid). + +mk_param(v1) -> "target_v1"; +mk_param(v2) -> "target_v2"; +mk_param(v3) -> "target_v3". + +mk_ip([A,B,C,D], Vsn) -> + io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]). + + +rewrite_target_addr_conf(Dir,NewPort) -> + TAFile = filename:join(Dir, "target_addr.conf"), + ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]), + case file:read_file_info(TAFile) of + {ok, _} -> ok; + {error, R} -> ?ERR("failure reading file info of " + "target address config file: ~p",[R]), + ok + end, + + ?line [TrapAddr|Addrs] = + snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end), + + ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]), + + NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs], + + ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]), + + ?line ok = file:rename(filename:join(Dir,"target_addr.conf"), + filename:join(Dir,"target_addr.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + + ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs), + + file:close(Fid). + +rewrite_target_addr_conf1(O) -> + {ok,O}. + +rewrite_target_addr_conf2(NewPort,{Name,Ip,_Port,Timeout,Retry, + "std_trap",EngineId}) -> + ?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]), + {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; +rewrite_target_addr_conf2(_NewPort,O) -> + ?LOG("rewrite_target_addr_conf2 -> entry with " + "~n O: ~p",[O]), + O. + + +rewrite_target_addr_conf3(_,[]) -> ok; +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry, + ParamName,EngineId}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % ParamsName + "\"~s\"}.", % EngineId + [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]), + rewrite_target_addr_conf3(Fid,T); +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList, + ParamName,EngineId,TMask,MMS}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % TagList + "\"~s\", " % ParamsName + "\"~s\"," % EngineId + "~p, " % TMask + "~p}.", % MMS + [Name,Ip,Port,Timeout,Retry,TagList,ParamName, + EngineId,TMask,MMS]), + rewrite_target_addr_conf3(Fid,T). + +reset_target_addr_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_addr.old"), + filename:join(Dir,"target_addr.conf")). + +write_target_params_conf(Dir, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + lists:foreach(fun(Vsn) -> + MP = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> v3 + end, + SM = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> usm + end, + ok = io:format(Fid, "{\"target_~w\", ~w, ~w, " + "\"all-rights\", noAuthNoPriv}.~n", + [Vsn, MP, SM]) + end, + Vsns), + file:close(Fid). + +rewrite_target_params_conf(Dir, SecName, SecLevel) -> + ?line ok = file:rename(filename:join(Dir,"target_params.conf"), + filename:join(Dir,"target_params.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n", + [SecName, SecLevel]), + file:close(Fid). + +reset_target_params_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_params.old"), + filename:join(Dir,"target_params.conf")). + +write_notify_conf(Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write), + ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []), + ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []), + file:close(Fid). + +ver_to_trap_str([v1]) -> "v1"; +ver_to_trap_str([v2]) -> "v2"; +% default is to use the latest snmp version +ver_to_trap_str([v1,v2]) -> "v2". + + + +write_view_conf(Dir) -> + {ok, Fid} = file:open(a(Dir,"view.conf"),write), + ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []), + ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]), + file:close(Fid). + +a(A,B) -> lists:append(A,B). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +copy_file(From, To) -> + {ok, Bin} = file:read_file(From), + ok = file:write_file(To, Bin). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +display_memory_usage() -> + Info = snmpa:info(snmp_master_agent), + TreeSize = lists_key1search(tree_size_bytes, Info), + ProcMem = lists_key1search(process_memory, Info), + MibDbSize = lists_key1search([db_memory,mib], Info), + NodeDbSize = lists_key1search([db_memory,node], Info), + TreeDbSize = lists_key1search([db_memory,tree], Info), + ?INF("Memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p", + [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]). + +lists_key1search([], Res) -> + Res; +lists_key1search([Key|Keys], List) when atom(Key), list(List) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + lists_key1search(Keys, Val); + false -> + undefined + end; +lists_key1search(Key, List) when atom(Key) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + Val; + false -> + undefined + end. + + +regs() -> + lists:sort(registered()). diff --git a/lib/snmp/test/snmp_agent_v3_test.erl b/lib/snmp/test/snmp_agent_v3_test.erl new file mode 100644 index 0000000000..823c914136 --- /dev/null +++ b/lib/snmp/test/snmp_agent_v3_test.erl @@ -0,0 +1,5657 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_agent_v3_test). + +%% TODO +%% * Test fault-tolerance (kill master etc) +%% + +-compile(export_all). + +-define(application, snmp). + +-include_lib("kernel/include/file.hrl"). +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). +%% -include_lib("snmp/include/SNMP-COMMUNITY-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-VIEW-BASED-ACM-MIB.hrl"). +%% -include_lib("snmp/include/SNMP-USER-BASED-SM-MIB.hrl"). + + +-define(klas1, [1,3,6,1,2,1,7]). +-define(klas2, [1,3,6,1,2,1,9]). +-define(klas3, [1,3,6,1,2,1,8,1]). +-define(klas4, [1,3,6,1,2,1,8,4]). +-define(sa, [1,3,6,1,4,1,193,2]). +-define(system, [1,3,6,1,2,1,1]). +-define(snmp, [1,3,6,1,2,1,11]). +-define(snmpTraps, [1,3,6,1,6,3,1,1,5]). +-define(ericsson, [1,3,6,1,4,1,193]). +-define(testTrap, [1,3,6,1,2,1,15,0]). +-define(xDescr, [1,3,6,1,2,1,17,1]). +-define(xDescr2, [1,3,6,1,2,1,17,2]). + +-define(active, 1). +-define(notInService, 2). +-define(notReady, 3). +-define(createAndGo, 4). +-define(createAndWait, 5). +-define(destroy, 6). + +-define(TRAP_UDP, 5000). + +-define(tooBigStr, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"). + +-define(str(X), snmp_pdus:bits_to_str(X)). + +-define(break(), begin io:format(user, "break at line ~w: pid: ~p\n", + [?LINE, self()]), + receive cont -> ok end + end). + + +-import(snmp_test_mgr, [gn/1, g/1, s/1, gb/3]). +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + +-define(v1_2_3(V1,V2,V3), + case get(vsn) of + v1 -> V1; + v2 -> V2; + _ -> V3 + end). + +all(suite) -> {req, + [mnesia, distribution, + {local_slave_nodes, 2}, {time, 360}], + [{conf, init_all, cases(), finish_all}]}. + +init_per_testcase(_Case, Config) when list(Config) -> + Dog = ?t:timetrap(?t:minutes(6)), + [{watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when list(Config) -> + Dog = ?config(watchdog, Config), + ?t:timetrap_cancel(Dog), + Config. + +cases() -> + case ?OSTYPE() of + vxworks -> + %% No crypto app, so skip v3 testcases + [ + app_info, + test_v1, test_v2, test_v1_v2, + test_multi_threaded, + mib_storage, + tickets]; + _Else -> + [ + app_info, + test_v1, test_v2, test_v1_v2, test_v3, + test_multi_threaded, + mib_storage, + tickets + ] + end. + + +%%%----------------------------------------------------------------- +%%% The test case structure is as follows: +%%% +%%% init_all - starts mnesia, +%%% +%%% init_v1 - starts agent +%%% simple +%%% big - e.g. starts/stops subagent, load/unloads mibs +%%% init_mul +%%% mul_get +%%% mul_set +%%% <etc> +%%% finish_mul +%%% <etc> +%%% finish_v1 +%%% +%%% init_v2 - starts agent +%%% finish_v2 +%%% +%%% init_bilingual - starts agent +%%% finish_bilingual +%%% +%%% finish_all +%%% +%%% There is still one problem with these testsuites. If one test +%%% fails, it may not be possible to run some other cases, as it +%%% may have e.g. created some row or loaded some table, that it +%%% didn't undo (since it failed). +%%%----------------------------------------------------------------- + +init_all(Config0) when list(Config0) -> + ?LOG("init_all -> entry with" + "~n Config0: ~p",[Config0]), + + %% -- + %% Fix config: + %% + + DataDir0 = ?config(data_dir, Config0), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + Config1 = lists:keydelete(data_dir, 1, Config0), + Config = [{data_dir, DataDir3 ++ "/"}|Config1], + + %% -- + %% Start nodes + %% + + ?line {ok, SaNode} = start_node(snmp_sa), + ?line {ok, MgrNode} = start_node(snmp_mgr), + + + %% -- + %% Create necessary files + %% + + Dir = ?config(priv_dir, Config), + ?DBG("init_all -> Dir ~p", [Dir]), + + DataDir = ?config(data_dir, Config), + ?DBG("init_all -> DataDir ~p", [DataDir]), + + file:make_dir(MgrDir = filename:join(Dir, "mgr_dir/")), + ?DBG("init_all -> MgrDir ~p", [MgrDir]), + + file:make_dir(AgentDir = filename:join(Dir, "agent_dir/")), + ?DBG("init_all -> AgentDir ~p", [AgentDir]), + + file:make_dir(SaDir = filename:join(Dir, "sa_dir/")), + ?DBG("init_all -> SaDir ~p", [SaDir]), + + + %% -- + %% Start and initiate mnesia + %% + + ?DBG("init_all -> load application mnesia", []), + ?line ok = application:load(mnesia), + + ?DBG("init_all -> load application mnesia on node ~p", [SaNode]), + ?line ok = rpc:call(SaNode, application, load, [mnesia]), + + ?DBG("init_all -> application mnesia: set_env dir",[]), + ?line application_controller:set_env(mnesia, dir, + filename:join(Dir, "Mnesia1")), + + ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]), + ?line rpc:call(SaNode, application_controller, set_env, + [mnesia, dir, filename:join(Dir, "Mnesia2")]), + + ?DBG("init_all -> create mnesia schema",[]), + ?line ok = mnesia:create_schema([SaNode, node()]), + + ?DBG("init_all -> start application mnesia",[]), + ?line ok = application:start(mnesia), + + ?DBG("init_all -> start application mnesia on ~p",[SaNode]), + ?line ok = rpc:call(SaNode, application, start, [mnesia]), + Ip = ?LOCALHOST(), + [{snmp_sa, SaNode}, + {snmp_mgr, MgrNode}, + {agent_dir, AgentDir ++ "/"}, + {mgr_dir, MgrDir ++ "/"}, + {sa_dir, SaDir ++ "/"}, + {mib_dir, DataDir}, + {ip, Ip} | + Config]. + +finish_all(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + stop_node(SaNode), + stop_node(MgrNode), + application:stop(mnesia). + +start_v1_agent(Config) when list(Config) -> + start_agent(Config, [v1]). + +start_v1_agent(Config,Opts) when list(Config), list(Opts) -> + start_agent(Config, [v1], Opts). + +start_v2_agent(Config) when list(Config) -> + start_agent(Config, [v2]). + +start_v3_agent(Config) when list(Config) -> + start_agent(Config, [v3]). + +start_bilingual_agent(Config) when list(Config) -> + start_agent(Config, [v1,v2]). + +start_multi_threaded_agent(Config) when list(Config) -> + start_agent(Config, [v2], [{snmp_multi_threaded, true}]). + +stop_agent(Config) when list(Config) -> + ?LOG("stop_agent -> entry with" + "~n Config: ~p",[Config]), + + {Sup, Par} = ?config(snmp_sup, Config), + ?DBG("stop_agent -> attempt to stop (sup) ~p" + "~n Sup: ~p" + "~n Par: ~p", + [Sup, + (catch process_info(Sup)), + (catch process_info(Par))]), + stop_sup(Sup, Par), + + {Sup2, Par2} = ?config(snmp_sub, Config), + ?DBG("stop_agent -> attempt to stop (sub) ~p" + "~n Sup2: ~p" + "~n Par2: ~p", + [Sup2, + (catch process_info(Sup2)), + (catch process_info(Par2))]), + stop_sup(Sup2, Par2), + + ?DBG("stop_agent -> done - now cleanup config", []), + C1 = lists:keydelete(snmp_sup, 1, Config), + lists:keydelete(snmp_sub, 1, C1). + + +stop_sup(Pid, _) when node(Pid) == node() -> + case (catch process_info(Pid)) of + PI when list(PI) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + exit(Pid, kill), + await_stopped(Pid, Ref); + {'EXIT', _Reason} -> + ?LOG("stop_sup -> ~p not running", [Pid]), + ok + end; +stop_sup(Pid, _) -> + ?LOG("stop_sup -> attempt to stop ~p", [Pid]), + Ref = erlang:monitor(process, Pid), + ?LOG("stop_sup -> Ref: ~p", [Ref]), + %% Pid ! {'EXIT', Parent, shutdown}, % usch + exit(Pid, kill), + await_stopped(Pid, Ref). + +await_stopped(Pid, Ref) -> + receive + {'DOWN', Ref, process, Pid, _Reason} -> + ?DBG("received down message for ~p", [Pid]), + ok + after 10000 -> + ?INF("await_stopped -> timeout for ~p",[Pid]), + erlang:demonitor(Ref), + ?FAIL({failed_stop,Pid}) + end. + + +start_agent(Config, Vsn) -> + start_agent(Config, Vsn, []). +start_agent(Config, Vsn, Opts) -> + ?LOG("start_agent -> entry (~p) with" + "~n Config: ~p" + "~n Vsn: ~p" + "~n Opts: ~p",[node(), Config, Vsn, Opts]), + + ?line AgentDir = ?config(agent_dir, Config), + ?line SaNode = ?config(snmp_sa, Config), + + snmp_app_env_init(vsn_init(Vsn) ++ + [{audit_trail_log, read_write_log}, + {audit_trail_log_dir, AgentDir}, + {audit_trail_log_size, {10240, 10}}, + {force_config_reload, false}, + {snmp_agent_type, master}, + {snmp_config_dir, AgentDir}, + {snmp_db_dir, AgentDir}, + {snmp_local_db_auto_repair, true}, + {snmp_master_agent_verbosity, trace}, + {snmp_supervisor_verbosity, trace}, + {snmp_mibserver_verbosity, trace}, + {snmp_symbolic_store_verbosity, trace}, + {snmp_note_store_verbosity, trace}, + {snmp_net_if_verbosity, trace}], + Opts), + + + process_flag(trap_exit,true), + + {ok, AppSup} = snmp_app_sup:start_link(), + unlink(AppSup), + ?DBG("start_agent -> snmp app supervisor: ~p",[AppSup]), + + ?DBG("start_agent -> start master agent (old style)",[]), + Sup = case (catch snmpa_app:start(normal)) of + {ok, S} -> + ?DBG("start_agent -> started, Sup: ~p",[S]), + S; + + Else -> + ?DBG("start_agent -> unknown result: ~n~p",[Else]), + %% Get info about the apps we depend on + MnesiaInfo = mnesia_running(), + ?FAIL({start_failed,Else,MnesiaInfo}) + end, + + ?DBG("start_agent -> unlink from supervisor",[]), + ?line unlink(Sup), + ?line SaDir = ?config(sa_dir, Config), + ?DBG("start_agent -> (rpc) start sub on ~p",[SaNode]), + ?line {ok, Sub} = rpc:call(SaNode, ?MODULE, start_sub, [SaDir]), + ?DBG("start_agent -> done",[]), + ?line [{snmp_sup, {Sup, self()}}, {snmp_sub, Sub} | Config]. + + +vsn_init(Vsn) -> + vsn_init([v1,v2,v3], Vsn, []). + +vsn_init([], _Vsn, Acc) -> + Acc; +vsn_init([V|Vsns], Vsn, Acc) -> + case lists:member(V, Vsn) of + true -> + vsn_init(Vsns, Vsn, [{V, true}|Acc]); + false -> + vsn_init(Vsns, Vsn, [{V, false}|Acc]) + end. + +snmp_app_env_init(Env0, Opts) -> + ?DBG("snmp_app_env_init -> unload snmp",[]), + ?line application:unload(snmp), + ?DBG("snmp_app_env_init -> load snmp",[]), + ?line application:load(snmp), + ?DBG("snmp_app_env_init -> initiate (snmp) application env",[]), + F1 = fun({Key,Val} = New, Acc0) -> + ?DBG("snmp_app_env_init -> " + "updating setting ~p to ~p", [Key, Val]), + case lists:keyreplace(Key, 1, Acc0, New) of + Acc0 -> + [New|Acc0]; + Acc -> + Acc + end + end, + Env = lists:foldr(F1, Env0, Opts), + ?DBG("snmp_app_env_init -> Env: ~p",[Env]), + F2 = fun({Key,Val}) -> + ?DBG("snmp_app_env_init -> setting ~p to ~p",[Key, Val]), + application_controller:set_env(snmp, Key, Val) + end, + lists:foreach(F2, Env). + + + + +%% Test if application is running +mnesia_running() -> ?IS_MNESIA_RUNNING(). +crypto_running() -> ?IS_CRYPTO_RUNNING(). + + +start_sub(Dir) -> + ?DBG("start_sub -> entry",[]), + Opts = [{db_dir, Dir}, + {supervisor, [{verbosity, trace}]}], + %% BMK BMK +% {ok, P} = snmp_supervisor:start_sub(Dir), + {ok, P} = snmpa_supervisor:start_sub_sup(Opts), + unlink(P), + {ok, {P, self()}}. + +create_tables(SaNode) -> + ?line {atomic, ok} = mnesia:create_table([{name, friendsTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, kompissTable2}, + {ram_copies, [SaNode]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}]), + ?line {atomic, ok} = mnesia:create_table([{name, snmp_variables}, + {attributes, [a1,a2]}]). + +delete_tables() -> + mnesia:delete_table(friendsTable2), + mnesia:delete_table(kompissTable2), + mnesia:delete_table(snmp_variables). + +%% Creation is done in runtime! +delete_mib_storage_mnesia_tables() -> + mnesia:delete_table(snmpa_mib_data), + mnesia:delete_table(snmpa_mib_tree), + mnesia:delete_table(snmpa_symbolic_store). + +%%----------------------------------------------------------------- +%% A test case is always one of: +%% - v1 specific case +%% - v2 specific case +%% - v1 and v2 case +%% All v1 specific cases are prefixed with v1_, and all v2 with +%% v2_. E.g. v1_trap/v2_trap. +%% +%% All other cases are shared. However, the testserver uses the name +%% of the case to generate a file for that case. The same case cannot +%% be used in different configurations in the same suite. Therefore +%% all these functions exists in two variants, the base function +%% <base>, and a second version <base>_2. There may be several +%% versions as well, <base>_N. +%%----------------------------------------------------------------- +mib_storage(suite) -> [ + mib_storage_ets, + mib_storage_dets, + mib_storage_mnesia, + mib_storage_size_check_ets, + mib_storage_size_check_dets, + mib_storage_size_check_mnesia, + mib_storage_varm_dets, + mib_storage_varm_mnesia + ]. + +mib_storage_ets(suite) -> {req, [], {conf, init_mib_storage_ets, + mib_storage_ets_cases(), + finish_mib_storage_ets}}. + +mib_storage_dets(suite) -> {req, [], {conf, init_mib_storage_dets, + mib_storage_dets_cases(), + finish_mib_storage_dets}}. + +mib_storage_mnesia(suite) -> {req, [], {conf, init_mib_storage_mnesia, + mib_storage_mnesia_cases(), + finish_mib_storage_mnesia}}. + +mib_storage_size_check_ets(suite) -> + {req, [], {conf, + init_size_check_mse, + mse_size_check_cases(), + finish_size_check_mse}}. + +mib_storage_size_check_dets(suite) -> + {req, [], {conf, + init_size_check_msd, + msd_size_check_cases(), + finish_size_check_msd}}. + +mib_storage_size_check_mnesia(suite) -> + {req, [], {conf, + init_size_check_msm, + msm_size_check_cases(), + finish_size_check_msm}}. + +mib_storage_varm_dets(suite) -> + {req, [], {conf, + init_varm_mib_storage_dets, + varm_mib_storage_dets_cases(), + finish_varm_mib_storage_dets}}. + +mib_storage_varm_mnesia(suite) -> + {req, [], {conf, + init_varm_mib_storage_mnesia, + varm_mib_storage_mnesia_cases(), + finish_varm_mib_storage_mnesia}}. + +mib_storage_ets_cases() -> + [ + mse_simple, + mse_v1_processing, + mse_big, + mse_big2, + mse_loop_mib, + mse_api, + mse_sa_register, + mse_v1_trap, + mse_sa_error, + mse_next_across_sa, + mse_undo, + mse_standard_mib, + mse_community_mib, + mse_framework_mib, + mse_target_mib, + mse_notification_mib, + mse_view_based_acm_mib, + mse_sparse_table, + mse_me_of, + mse_mib_of]. + +mib_storage_dets_cases() -> + [ + msd_simple, + msd_v1_processing, + msd_big, + msd_big2, + msd_loop_mib, + msd_api, + msd_sa_register, + msd_v1_trap, + msd_sa_error, + msd_next_across_sa, + msd_undo, + msd_standard_mib, + msd_community_mib, + msd_framework_mib, + msd_target_mib, + msd_notification_mib, + msd_view_based_acm_mib, + msd_sparse_table, + msd_me_of, + msd_mib_of + ]. + +mib_storage_mnesia_cases() -> + [ + msm_simple, + msm_v1_processing, + msm_big, + msm_big2, + msm_loop_mib, + msm_api, + msm_sa_register, + msm_v1_trap, + msm_sa_error, + msm_next_across_sa, + msm_undo, + msm_standard_mib, + msm_community_mib, + msm_framework_mib, + msm_target_mib, + msm_notification_mib, + msm_view_based_acm_mib, + msm_sparse_table, + msm_me_of, + msm_mib_of + ]. + +mse_size_check_cases() -> + [mse_size_check]. + +msd_size_check_cases() -> + [msd_size_check]. + +msm_size_check_cases() -> + [msm_size_check]. + +varm_mib_storage_dets_cases() -> + [msd_varm_mib_start]. + +varm_mib_storage_mnesia_cases() -> + [msm_varm_mib_start]. + +init_mib_storage_ets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,ets}, + init_ms(Config, [MibStorage]). + +init_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + init_ms(Config, [MibStorage]). + +init_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + init_ms(Config, [MibStorage]). + +init_ms(Config, Opts) when list(Config) -> + ?LOG("init_mib_storage_ets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts], + [{vsn, v1} | start_v1_agent(Config,Opts1)]. + +init_size_check_mse(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, ets}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msd(Config) when list(Config) -> + AgentDir = ?GCONF(agent_dir, Config), + MibStorage = {snmp_mib_storage, {dets, AgentDir}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_msm(Config) when list(Config) -> + MibStorage = {snmp_mib_storage, {mnesia,[]}}, + init_size_check_ms(Config, [MibStorage]). + +init_size_check_ms(Config, Opts) when list(Config) -> + SaNode = ?GCONF(snmp_sa, Config), + %% We are using v3 here, so crypto must be supported or else... + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + create_tables(SaNode), + AgentDir = ?GCONF(agent_dir, Config), + MgrDir = ?GCONF(mgr_dir, Config), + Ip = ?GCONF(ip, Config), + ?line ok = + config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_agent(Config, [v3], Opts)]. + +init_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_dets -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +init_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("init_varm_mib_storage_mnesia -> entry", []), + ?line SaNode = ?GCONF(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?GCONF(agent_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage,{mnesia,[]}}, + MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, + MibsVerbosity = {snmp_mibserver_verbosity, trace}, + SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, + Opts = [MibStorage,MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity], + [{vsn, v1}, {agent_opts,Opts} | Config]. + +finish_mib_storage_ets(Config) when list(Config) -> + ?LOG("finish_mib_storage_ets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_mib_storage_dets -> entry", []), + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + C1 = stop_agent(Config), + delete_files(C1), + C2 = lists:keydelete(vsn, 1, C1), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_dets(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_dets -> entry", []), + delete_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_varm_mib_storage_mnesia(Config) when list(Config) -> + ?LOG("finish_varm_mib_storage_mnesia -> entry", []), + delete_tables(), + delete_mib_storage_mnesia_tables(), + %% C1 = stop_agent(Config), % In case something went wrong... + delete_files(Config), + C2 = lists:keydelete(vsn, 1, Config), + lists:keydelete(agent_opts, 1, C2). + +finish_size_check_mse(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msd(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_msm(Config) when list(Config) -> + finish_size_check_ms(Config). + +finish_size_check_ms(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + + +%% These are just interface functions to fool the test server +mse_simple(X) -> simple(X). +mse_v1_processing(X) -> v1_processing(X). +mse_big(X) -> big(X). +mse_big2(X) -> big2(X). +mse_loop_mib(X) -> loop_mib(X). +mse_api(X) -> api(X). +mse_sa_register(X) -> sa_register(X). +mse_v1_trap(X) -> v1_trap(X). +mse_sa_error(X) -> sa_error(X). +mse_next_across_sa(X) -> next_across_sa(X). +mse_undo(X) -> undo(X). +mse_standard_mib(X) -> snmp_standard_mib(X). +mse_community_mib(X) -> snmp_community_mib(X). +mse_framework_mib(X) -> snmp_framework_mib(X). +mse_target_mib(X) -> snmp_target_mib(X). +mse_notification_mib(X) -> snmp_notification_mib(X). +mse_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +mse_sparse_table(X) -> sparse_table(X). +mse_me_of(X) -> ms_me_of(X). +mse_mib_of(X) -> ms_mib_of(X). + +msd_simple(X) -> simple(X). +msd_v1_processing(X) -> v1_processing(X). +msd_big(X) -> big(X). +msd_big2(X) -> big2(X). +msd_loop_mib(X) -> loop_mib(X). +msd_api(X) -> api(X). +msd_sa_register(X) -> sa_register(X). +msd_v1_trap(X) -> v1_trap(X). +msd_sa_error(X) -> sa_error(X). +msd_next_across_sa(X) -> next_across_sa(X). +msd_undo(X) -> undo(X). +msd_standard_mib(X) -> snmp_standard_mib(X). +msd_community_mib(X) -> snmp_community_mib(X). +msd_framework_mib(X) -> snmp_framework_mib(X). +msd_target_mib(X) -> snmp_target_mib(X). +msd_notification_mib(X) -> snmp_notification_mib(X). +msd_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msd_sparse_table(X) -> sparse_table(X). +msd_me_of(X) -> ms_me_of(X). +msd_mib_of(X) -> ms_mib_of(X). + +msm_simple(X) -> simple(X). +msm_v1_processing(X) -> v1_processing(X). +msm_big(X) -> big(X). +msm_big2(X) -> big2(X). +msm_loop_mib(X) -> loop_mib(X). +msm_api(X) -> api(X). +msm_sa_register(X) -> sa_register(X). +msm_v1_trap(X) -> v1_trap(X). +msm_sa_error(X) -> sa_error(X). +msm_next_across_sa(X) -> next_across_sa(X). +msm_undo(X) -> undo(X). +msm_standard_mib(X) -> snmp_standard_mib(X). +msm_community_mib(X) -> snmp_community_mib(X). +msm_framework_mib(X) -> snmp_framework_mib(X). +msm_target_mib(X) -> snmp_target_mib(X). +msm_notification_mib(X) -> snmp_notification_mib(X). +msm_view_based_acm_mib(X) -> snmp_view_based_acm_mib(X). +msm_sparse_table(X) -> sparse_table(X). +msm_me_of(X) -> ms_me_of(X). +msm_mib_of(X) -> ms_mib_of(X). + + +mse_size_check(X) -> p("mse_size_check..."), ms_size_check(X). +msd_size_check(X) -> p("msd_size_check..."), ms_size_check(X). +msm_size_check(X) -> p("msm_size_check..."), ms_size_check(X). + +msd_varm_mib_start(X) -> p("msd_varm_mib_start..."), varm_mib_start(X). +msm_varm_mib_start(X) -> p("msm_varm_mib_start..."), varm_mib_start(X). + +ms_size_check(suite) -> []; +ms_size_check(Config) when list(Config) -> + p("ms_size_check..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?LOG("mib server size check...", []), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMPv2-MIB"), + ?line load_master_std("SNMPv2-TM"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMPv2-MIB"), + ?line unload_master("SNMPv2-TM"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + + +varm_mib_start(suite) -> []; +varm_mib_start(Config) when list(Config) -> + p("varm_mib_start..."), + ?LOG("varm_mib_start -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + %% Start the agent + Opts = ?GCONF(agent_opts, Config), + Config1 = start_v1_agent(Config, Opts), + + %% Sleep some in order for the agent to start properly + ?DBG("varm_mib_start -> sleep some (before loading mobs)", []), + ?SLEEP(5000), + + %% Load all the mibs + HardwiredMibs = loaded_mibs(), + ?DBG("varm_mib_start -> load all mibs", []), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + + %% Unload the hardwired mibs + ?DBG("varm_mib_start -> sleep some (before unloading hardwired mibs)", []), + ?SLEEP(1000), + ?DBG("varm_mib_start -> unload (hardwired) mibs", []), + ?line unload_mibs(HardwiredMibs), %% unload hardwired + + ?DBG("varm_mib_start -> sleep some (before stopping agent)", []), + ?SLEEP(1000), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + Config2 = stop_agent(Config1), + + %% Sleep some in order for the agent to stop properly + ?DBG("varm_mib_start -> sleep some (before re-starting the agent)", []), + ?SLEEP(5000), + + %% Start the agent (again) + ?DBG("varm_mib_start -> start the agent", []), + Config3 = start_v1_agent(Config2, Opts), + + ?DBG("varm_mib_start -> sleep some (before starting tests)", []), + ?SLEEP(5000), + + %% Perform the test(s) + ?DBG("varm_mib_start -> perform the tests", []), + try_test(snmp_community_mib), + try_test(snmp_framework_mib), + try_test(snmp_target_mib), + try_test(snmp_notification_mib), + + %% Stop the agent (without deleting the stored files) + ?DBG("varm_mib_start -> stop the agent", []), + stop_agent(Config3), + ok. + + +-define(snmpTrapCommunity_instance, [1,3,6,1,6,3,18,1,4,0]). +-define(vacmViewSpinLock_instance, [1,3,6,1,6,3,16,1,5,1,0]). +-define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +ms_me_of(suite) -> []; +ms_me_of(Config) when list(Config) -> + p("ms_me_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_me_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = me_of(?snmpTrapCommunity_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = me_of(?vacmViewSpinLock_instance), + + ?DBG("ms_me_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = me_of(?usmStatsNotInTimeWindows_instance), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +me_of(Oid) -> + case snmpa:me_of(Oid) of + {ok, #me{oid = Oid}} -> + ok; + {ok, #me{oid = OtherOid}} -> + case lists:reverse(Oid) of + [0|Rest] -> + case lists:reverse(Rest) of + OtherOid -> + ok; + AnotherOid -> + {error, {invalid_oid, Oid, AnotherOid}} + end; + _ -> + {error, {invalid_oid, Oid, OtherOid}} + end; + {error, Reason} -> + {error, Reason}; + Else -> + {error, Else} + end. + + +ms_mib_of(suite) -> []; +ms_mib_of(Config) when list(Config) -> + p("ms_mib_of..."), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + ?line load_master_std("OTP-SNMPEA-MIB"), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + + ?SLEEP(2000), + + ?line display_memory_usage(), + + + ?DBG("ms_mib_of -> find ~w from SNMP-COMMUNITY-MIB", + [?snmpTrapCommunity_instance]), + ?line ok = mib_of(?snmpTrapCommunity_instance, 'SNMP-COMMUNITY-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-VIEW-BASED-ACM-MIB", + [?vacmViewSpinLock_instance]), + ?line ok = mib_of(?vacmViewSpinLock_instance, 'SNMP-VIEW-BASED-ACM-MIB'), + + ?DBG("ms_mib_of -> find ~w from SNMP-USER-BASED-SM-MIB", + [?usmStatsNotInTimeWindows_instance]), + ?line {error, _} = mib_of(?usmStatsNotInTimeWindows_instance, + 'SNMP-USER-BASED-SM-MIB'), + + + ?line unload_master("OTP-SNMPEA-MIB"), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + + ok. + +mib_of(Oid, ExpectedMibName) -> + ?DBG("mib_of -> entry with" + "~n Oid: ~p" + "~n ExpectedMibName: ~p", [Oid, ExpectedMibName]), + %% case snmpa:mib_of(Oid) of + MibOf = snmpa:mib_of(Oid), + ?DBG("mib_of -> MibOf: ~n~p", [MibOf]), + case MibOf of + {ok, ExpectedMibName} -> + ok; + {ok, OtherMibName} -> + {error, {invalid_mib, ExpectedMibName, OtherMibName}}; + {error, Reason} -> + {error, Reason}; + Else -> + ?DBG("mib_of -> Else: ~n~p", [Else]), + {error, Else} + end. + + +app_info(suite) -> []; +app_info(Config) when list(Config) -> + SnmpDir = app_dir(snmp), + SslDir = app_dir(ssl), + CryptoDir = app_dir(crypto), + Attr = snmp:module_info(attributes), + AppVsn = + case lists:keysearch(app_vsn, 1, Attr) of + {value, {app_vsn, V}} -> + V; + false -> + "undefined" + end, + io:format("Root dir: ~s~n" + "SNMP: Application dir: ~s~n" + " Application ver: ~s~n" + "SSL: Application dir: ~s~n" + "CRYPTO: Application dir: ~s~n", + [code:root_dir(), SnmpDir, AppVsn, SslDir, CryptoDir]), + ok. + +app_dir(App) -> + case code:lib_dir(App) of + D when list(D) -> + filename:basename(D); + {error, _Reason} -> + "undefined" + end. + + +test_v1(suite) -> {req, [], {conf, init_v1, v1_cases(), finish_v1}}. + +%v1_cases() -> [loop_mib]; +v1_cases() -> + [simple, + db_notify_client, + v1_processing, big, big2, loop_mib, + api, subagent, mnesia, multiple_reqs, + sa_register, v1_trap, sa_error, next_across_sa, undo, reported_bugs, + standard_mibs, sparse_table, cnt_64, + opaque, + % opaque]. + + change_target_addr_config]. + +init_v1(Config) when list(Config) -> + ?line SaNode = ?config(snmp_sa, Config), + ?line create_tables(SaNode), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v1} | start_v1_agent(Config)]. + +finish_v1(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v2(suite) -> {req, [], {conf, init_v2, v2_cases(), finish_v2}}. + +%v2_cases() -> [loop_mib_2]; +v2_cases() -> + [simple_2, v2_processing, big_2, big2_2, loop_mib_2, + api_2, subagent_2, mnesia_2, + multiple_reqs_2, sa_register_2, v2_trap, v2_inform, sa_error_2, + next_across_sa_2, undo_2, reported_bugs_2, standard_mibs_2, + v2_types, implied, sparse_table_2, cnt_64_2, opaque_2, v2_caps]. + +init_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_v2_agent(Config)]. + +finish_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v1_v2(suite) -> {req, [], {conf, init_v1_v2, v1_v2_cases(), finish_v1_v2}}. + +v1_v2_cases() -> + [simple_bi]. + +init_v1_v2(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, bilingual} | start_bilingual_agent(Config)]. + +finish_v1_v2(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_v3(suite) -> {req, [], {conf, init_v3, v3_cases(), finish_v3}}. + +%v3_cases() -> [loop_mib_3]; +v3_cases() -> + [simple_3, v3_processing, + big_3, big2_3, api_3, subagent_3, mnesia_3, loop_mib_3, + multiple_reqs_3, sa_register_3, v3_trap, v3_inform, sa_error_3, + next_across_sa_3, undo_3, reported_bugs_3, standard_mibs_3, + v3_security, + v2_types_3, implied_3, sparse_table_3, cnt_64_3, opaque_3, v2_caps_3]. + +init_v3(Config) when list(Config) -> + %% Make sure crypto works, otherwise start_agent will fail + %% and we will be stuck with a bunch of mnesia tables for + %% the rest of this suite... + ?DBG("start_agent -> start crypto app",[]), + case os:type() of + vxworks -> + no_crypto; + _ -> + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end + end, + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v3], MgrDir, AgentDir, + tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v3} | start_v3_agent(Config)]. + +finish_v3(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +test_multi_threaded(suite) -> {req, [], {conf, init_mt, mt_cases(), finish_mt}}. + +mt_cases() -> + [multi_threaded, mt_trap]. + +init_mt(Config) when list(Config) -> + SaNode = ?config(snmp_sa, Config), + create_tables(SaNode), + AgentDir = ?config(agent_dir, Config), + MgrDir = ?config(mgr_dir, Config), + Ip = ?config(ip, Config), + ?line ok = config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + [{vsn, v2} | start_multi_threaded_agent(Config)]. + +finish_mt(Config) when list(Config) -> + delete_tables(), + C1 = stop_agent(Config), + delete_files(C1), + lists:keydelete(vsn, 1, C1). + +%% This one *must* be run first in each case. +init_case(Config) when list(Config) -> + ?DBG("init_case -> entry with" + "~n Config: ~p", [Config]), + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + MasterNode = node(), + + SaHost = ?HOSTNAME(SaNode), + MgrHost = ?HOSTNAME(MgrNode), + MasterHost = ?HOSTNAME(MasterNode), + {ok, MasterIP} = snmp_misc:ip(MasterHost), + {ok, MIP} = snmp_misc:ip(MgrHost), + {ok, SIP} = snmp_misc:ip(SaHost), + + + put(mgr_node, MgrNode), + put(sa_node, SaNode), + put(master_node, MasterNode), + put(sa_host, SaHost), + put(mgr_host, MgrHost), + put(master_host, MasterHost), + put(mip, tuple_to_list(MIP)), + put(masterip , tuple_to_list(MasterIP)), + put(sip, tuple_to_list(SIP)), + + MibDir = ?config(mib_dir, Config), + put(mib_dir, MibDir), + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + put(std_mib_dir, StdM), + + MgrDir = ?config(mgr_dir, Config), + put(mgr_dir, MgrDir), + + put(vsn, ?config(vsn, Config)), + ?DBG("init_case -> exit with" + "~n MasterNode: ~p" + "~n SaNode: ~p" + "~n MgrNode: ~p" + "~n MibDir: ~p", [MasterNode, SaNode, MgrNode, MibDir]), + {SaNode, MgrNode, MibDir}. + +load_master(Mib) -> + ?DBG("load_master -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(mib_dir) ++ Mib]). + +load_master_std(Mib) -> + ?DBG("load_master_std -> entry with" + "~n Mib: ~p", [Mib]), + snmpa:unload_mibs(snmp_master_agent, [Mib]), % Unload for safety + ok = snmpa:load_mibs(snmp_master_agent, [get(std_mib_dir) ++ Mib]). + +unload_master(Mib) -> + ?DBG("unload_master -> entry with" + "~n Mib: ~p", [Mib]), + ok = snmpa:unload_mibs(snmp_master_agent, [Mib]). + +loaded_mibs() -> + ?DBG("loaded_mibs -> entry",[]), + Info = snmpa:info(snmp_master_agent), + {value, {loaded_mibs, Mibs}} = lists:keysearch(loaded_mibs, 1, Info), + [atom_to_list(Mib) || {Mib,_,_} <- Mibs]. + +unload_mibs(Mibs) -> + ?DBG("unload_mibs -> entry with" + "~n Mibs: ~p", [Mibs]), + ok = snmpa:unload_mibs(snmp_master_agent, Mibs). + +start_subagent(SaNode, RegTree, Mib) -> + ?DBG("start_subagent -> entry with" + "~n SaNode: ~p" + "~n RegTree: ~p" + "~n Mib: ~p", [SaNode, RegTree, Mib]), + MA = whereis(snmp_master_agent), + ?DBG("start_subagent -> MA: ~p", [MA]), + MibDir = get(mib_dir), + Mib1 = join(MibDir,Mib), + %% BMK BMK +% case rpc:call(SaNode,snmp_supervisor,start_subagent,[MA,RegTree,[Mib1]]) of + case rpc:call(SaNode, snmpa_supervisor, + start_sub_agent, [MA, RegTree, [Mib1]]) of + {ok, SA} -> + ?DBG("start_subagent -> SA: ~p", [SA]), + {ok, SA}; + Error -> + ?FAIL({subagent_start_failed, SaNode, Error, [MA, RegTree, Mib1]}) + end. + +stop_subagent(SA) -> + ?DBG("stop_subagent -> entry with" + "~n SA: ~p", [SA]), + %% BNK BMK + %% rpc:call(node(SA), snmp_supervisor, stop_subagent, [SA]). + rpc:call(node(SA), snmpa_supervisor, stop_sub_agent, [SA]). + +%%----------------------------------------------------------------- +%% This function takes care of the old OTP-SNMPEA-MIB. +%% Unfortunately, the testcases were written to use the data in the +%% internal tables, and these table are now obsolete and not used +%% by the agent. Therefore, we emulate them by using +%% OLD-SNMPEA-MIB, which uses the default impl. of all tables. +%% +%% These two rows must exist in intCommunityTable +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. +%% (But with the manager's IP address) +%% +%%----------------------------------------------------------------- +init_old() -> + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [6 | "public"], + {get(mip), "public", 2, 2}), + snmpa_local_db:table_create_row(intCommunityTable, + get(mip) ++ [13 | "standard trap"], + {get(mip), "standard trap", 2, 1}), + snmpa_local_db:variable_set(intAgentIpAddress, [127,0,0,1]). + + + +simple(suite) -> []; +simple(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(simple_standard_test). + +simple_2(X) -> simple(X). + +simple_bi(suite) -> []; +simple_bi(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(vsn, v1), % First, try v1 manager + try_test(simple_standard_test), + + put(vsn, v2), % Then, try v2 manager + try_test(simple_standard_test). + +simple_3(X) -> + simple(X). + +big(suite) -> []; +big(Config) when list(Config) -> + ?DBG("big -> entry", []), + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?DBG("big -> SA: ~p", [SA]), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB"). + +big_2(X) -> big(X). + +big_3(X) -> big(X). + + +big2(suite) -> []; +big2(Config) when list(Config) -> + %% This is exactly the same tests as 'big', but with the + %% v2 equivalent of the mibs. + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent..."), + ?line pong = net_adm:ping(SaNode), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1-v2"), + ?line load_master("OLD-SNMPEA-MIB-v2"), + ?line init_old(), + try_test(big_test), + ?line stop_subagent(SA), + ?line unload_master("OLD-SNMPEA-MIB-v2"). + +big2_2(X) -> big2(X). + +big2_3(X) -> big2(X). + + +multi_threaded(suite) -> []; +multi_threaded(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(multi_threaded_test), + ?line unload_master("Test1"). + +mt_trap(suite) -> []; +mt_trap(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + ?line load_master("TestTrapv2"), + try_test(mt_trap_test, [MA]), + ?line unload_master("TestTrapv2"), + ?line unload_master("Test1"). + +v2_types(suite) -> []; +v2_types(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(types_v2_test), + ?line unload_master("Test1"). + +v2_types_3(X) -> v2_types(X). + + +implied(suite) -> []; +implied(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(implied_test,[MA]), + ?line unload_master("Test1"). + +implied_3(X) -> implied(X). + + +sparse_table(suite) -> []; +sparse_table(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(sparse_table_test), + ?line unload_master("Test1"). + +sparse_table_2(X) -> sparse_table(X). + +sparse_table_3(X) -> sparse_table(X). + +cnt_64(suite) -> []; +cnt_64(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line load_master("Test1"), + try_test(cnt_64_test, [MA]), + ?line unload_master("Test1"). + +cnt_64_2(X) -> cnt_64(X). + +cnt_64_3(X) -> cnt_64(X). + +opaque(suite) -> []; +opaque(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test1"), + try_test(opaque_test), + ?line unload_master("Test1"). + +opaque_2(X) -> opaque(X). + +opaque_3(X) -> opaque(X). + + +change_target_addr_config(suite) -> []; +change_target_addr_config(Config) when list(Config) -> + p("Testing changing target address config..."), + ?LOG("change_target_addr_config -> entry",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + put(sname,snmp_suite), + put(verbosity,trace), + + MA = whereis(snmp_master_agent), + + ?LOG("change_target_addr_config -> load TestTrap",[]), + ?line load_master("TestTrap"), + + ?LOG("change_target_addr_config -> set trace verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,trace), + + %% First send some traps that will arive att the original manager + ?LOG("change_target_addr_config -> send trap",[]), + try_test(ma_trap1, [MA]), + + ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]), + ?line snmpa:verbosity(local_db,silence), + + %% Start new dummy listener + ?LOG("change_target_addr_config -> start dummy manager",[]), + ?line {ok,Pid,NewPort} = dummy_manager_start(MA), + + %% Reconfigure + ?LOG("change_target_addr_config -> reconfigure",[]), + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_addr_conf(AgentDir, NewPort), + ?line snmp_target_mib:reconfigure(AgentDir), + + %% Send the trap again + ?LOG("change_target_addr_config -> send trap again",[]), + catch dummy_manager_send_trap2(Pid), + + ?LOG("change_target_addr_config -> await trap ack",[]), + catch dummy_manager_await_trap2_ack(), + + ?LOG("change_target_addr_config -> stop dummy manager",[]), + ?line ok = dummy_manager_stop(Pid), + + ?LOG("change_target_addr_config -> reset target address config",[]), + ?line reset_target_addr_conf(AgentDir), + + ?LOG("change_target_addr_config -> unload TestTrap",[]), + ?line unload_master("TestTrap"). + + +dummy_manager_start(MA) -> + ?DBG("dummy_manager_start -> entry",[]), + Pid = spawn(get(mgr_node), ?MODULE,dummy_manager_init,[self(),MA]), + ?DBG("dummy_manager_start -> Pid: ~p",[Pid]), + await_dummy_manager_started(Pid). + +await_dummy_manager_started(Pid) -> + receive + {dummy_manager_started,Pid,Port} -> + ?DBG("dummy_manager_start -> acknowledge received with" + "~n Port: ~p",[Port]), + {ok,Pid,Port}; + {'EXIT', Pid, Reason} -> + {error, Pid, Reason}; + O -> + ?LOG("dummy_manager_start -> received unknown message:" + "~n ~p",[O]), + await_dummy_manager_started(Pid) + end. + +dummy_manager_stop(Pid) -> + ?DBG("dummy_manager_stop -> entry with Pid: ~p",[Pid]), + Pid ! stop, + receive + {dummy_manager_stopping, Pid} -> + ?DBG("dummy_manager_stop -> acknowledge received",[]), + ok + after 10000 -> + ?ERR("dummy_manager_stop -> timeout",[]), + timeout + end. + +dummy_manager_send_trap2(Pid) -> + ?DBG("dummy_manager_send_trap2 -> entry",[]), + Pid ! {send_trap,testTrap2}. + +dummy_manager_await_trap2_ack() -> + ?DBG("dummy_manager_await_trap2 -> entry",[]), + receive + {received_trap,Trap} -> + ?LOG("dummy_manager_await_trap2 -> received trap: ~p",[Trap]), + %% Note: + %% Without this sleep the v2_inform_i testcase failes! There + %% is no relation between these two test cases as far as I + %% able to figure out... + sleep(60000), + ok; + O -> + ?ERR("dummy_manager_await_trap2 -> unexpected message: ~p",[O]), + ok + after 10000 -> + ?ERR("dummy_manager_await_trap2 -> timeout",[]), + timeout + end. + +dummy_manager_init(Parent,MA) -> + ?DBG("dummy_manager_init -> entry with" + "~n Parent: ~p" + "~n MA: ~p",[Parent,MA]), + {ok,S} = gen_udp:open(0,[{recbuf,65535}]), + ?DBG("dummy_manager_init -> S: ~p",[S]), + {ok,Port} = inet:port(S), + ?DBG("dummy_manager_init -> Port: ~p",[Port]), + Parent ! {dummy_manager_started,self(),Port}, + dummy_manager_loop(Parent,S,MA). + +dummy_manager_loop(P,S,MA) -> + ?LOG("dummy_manager_loop -> ready for receive",[]), + receive + {send_trap,Trap} -> + ?LOG("dummy_manager_loop -> received trap send request" + "~n Trap: ~p",[Trap]), + snmpa:send_trap(MA, Trap, "standard trap"), + dummy_manager_loop(P,S,MA); + {udp, _UdpId, Ip, UdpPort, Bytes} -> + ?LOG("dummy_manager_loop -> received upd message" + "~n from: ~p:~p" + "~n size: ~p", + [Ip, UdpPort, dummy_manager_message_sz(Bytes)]), + R = dummy_manager_handle_message(Bytes), + ?DBG("dummy_manager_loop -> R: ~p",[R]), + P ! R, + dummy_manager_loop(P,S,MA); + stop -> + ?DBG("dummy_manager_loop -> received stop request",[]), + P ! {dummy_manager_stopping, self()}, + gen_udp:close(S), + exit(normal); + O -> + ?LOG("dummy_manager_loop -> received unknown message:" + "~n ~p",[O]), + dummy_manager_loop(P,S,MA) + end. + +dummy_manager_message_sz(B) when binary(B) -> + size(B); +dummy_manager_message_sz(L) when list(L) -> + length(L); +dummy_manager_message_sz(_) -> + undefined. + +dummy_manager_handle_message(Bytes) -> + case (catch snmp_pdus:dec_message(Bytes)) of + {'EXIT',Reason} -> + ?ERR("dummy_manager_handle_message -> " + "failed decoding message only:~n ~p",[Reason]), + {error,Reason}; + M -> + ?DBG("dummy_manager_handle_message -> decoded message:" + "~n ~p",[M]), + {received_trap,M} + end. + + +api(suite) -> []; +api(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(api_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +api_2(X) -> api(X). + +api_3(X) -> api(X). + + +subagent(suite) -> []; +subagent(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + try_test(load_test_sa), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + + p("Loading previous subagent mib in master and testing..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas1"]), + try_test(load_test), + + p("Unloading previous subagent mib in master and testing..."), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas1"]), + try_test(unreg_test), + p("Testing register subagent..."), + rpc:call(SaNode, snmp, register_subagent, + [MA, ?klas1, SA]), + try_test(load_test_sa), + + ?line stop_subagent(SA), + try_test(unreg_test). + +subagent_2(X) -> subagent(X). + +subagent_3(X) -> subagent(X). + + +mnesia(suite) -> []; +mnesia(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Starting subagent with mnesia impl..."), + {ok, SA} = start_subagent(SaNode, ?klas2, "Klas2"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + + try_test(big_test_2), + + p("Testing unregister subagent..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, SA]), + try_test(unreg_test), + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA). + +mnesia_2(X) -> mnesia(X). + +mnesia_3(X) -> mnesia(X). + + +multiple_reqs(suite) -> + {req, [], {conf, init_mul, mul_cases(), finish_mul}}. + +mul_cases() -> + [mul_get, mul_get_err, mul_next, mul_next_err, mul_set_err]. + +multiple_reqs_2(suite) -> + {req, [], {conf, init_mul, mul_cases_2(), finish_mul}}. + +multiple_reqs_3(_X) -> + {req, [], {conf, init_mul, mul_cases_3(), finish_mul}}. + + +mul_cases_2() -> + [mul_get_2, mul_get_err_2, mul_next_2, mul_next_err_2, mul_set_err_2]. + + +mul_cases_3() -> + [mul_get_3, mul_get_err_3, mul_next_3, mul_next_err_3, mul_set_err_3]. + + +init_mul(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + [{mul_sub, SA} | Config]. + +finish_mul(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + SA = ?config(mul_sub, Config), + + ?line unload_master("OLD-SNMPEA-MIB"), + ?line stop_subagent(SA), + lists:keydelete(mul_sub, 1, Config). + +mul_get(suite) -> []; +mul_get(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get..."), + try_test(do_mul_get). + +mul_get_2(X) -> mul_get(X). + +mul_get_3(X) -> mul_get(X). + + +mul_get_err(suite) -> []; +mul_get_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple get with error..."), + try_test(do_mul_get_err). + +mul_get_err_2(X) -> mul_get_err(X). + +mul_get_err_3(X) -> mul_get_err(X). + + +mul_next(suite) -> []; +mul_next(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next). + +mul_next_2(X) -> mul_next(X). + +mul_next_3(X) -> mul_next(X). + + +mul_next_err(suite) -> []; +mul_next_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple next..."), + try_test(do_mul_next_err). + +mul_next_err_2(X) -> mul_next_err(X). + +mul_next_err_3(X) -> mul_next_err(X). + + +mul_set(suite) -> []; +mul_set(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set..."), + try_test(do_mul_set). + +mul_set_2(X) -> mul_set(X). + +mul_set_3(X) -> mul_set(X). + + +mul_set_err(suite) -> []; +mul_set_err(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing multiple set with error..."), + try_test(do_mul_set_err). + +mul_set_err_2(X) -> mul_set_err(X). + +mul_set_err_3(X) -> mul_set_err(X). + + +sa_register(suite) -> []; +sa_register(Config) when list(Config) -> + ?DBG("sa_register -> entry", []), + {SaNode, _MgrNode, MibDir} = init_case(Config), + + ?DBG("sa_register -> start subagent", []), + ?line {ok, SA} = start_subagent(SaNode, ?klas1, "Klas1"), + + ?DBG("sa_register -> unregister subagent", []), + p("Testing unregister subagent (2)..."), + MA = whereis(snmp_master_agent), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Loading SA-MIB..."), + ?DBG("sa_register -> unload mibs", []), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + ?DBG("sa_register -> unload mibs", []), + snmpa:load_mibs(SA, [MibDir ++ "SA-MIB"]), + ?DBG("sa_register -> register subagent", []), + rpc:call(SaNode, snmp, register_subagent, [MA,?sa,SA]), + try_test(sa_mib), + + ?DBG("sa_register -> stop subagent", []), + ?line stop_subagent(SA). + +sa_register_2(X) -> sa_register(X). + +sa_register_3(X) -> sa_register(X). + + +v1_trap(suite) -> []; +v1_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_trap1, [MA]), + try_test(ma_trap2, [MA]), + try_test(ma_v2_2_v1_trap, [MA]), + try_test(ma_v2_2_v1_trap2, [MA]), + + p("Testing trap sending from subagent..."), + try_test(sa_trap1, [SA]), + try_test(sa_trap2, [SA]), + try_test(sa_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v2_trap(suite) -> []; +v2_trap(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing trap sending from master agent..."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + + try_test(ma_v2_trap1, [MA]), + try_test(ma_v2_trap2, [MA]), + try_test(ma_v1_2_v2_trap, [MA]), + try_test(ma_v1_2_v2_trap2, [MA]), + + try_test(sa_mib), + p("Testing trap sending from subagent..."), + try_test(sa_v1_2_v2_trap1, [SA]), + try_test(sa_v1_2_v2_trap2, [SA]), + try_test(sa_v1_2_v2_trap3, [SA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"), + + ?line stop_subagent(SA). + +v3_trap(X) -> + v2_trap(X). + +v2_inform(suite) -> + {req, [], {conf, init_v2_inform, [v2_inform_i], finish_v2_inform}}. + +v3_inform(_X) -> + %% v2_inform(X). + {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}. + +init_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +init_v3_inform(X) -> + init_v2_inform(X). + +finish_v2_inform(Config) when list(Config) -> + _Dir = ?config(agent_dir, Config), +% snmp_internal_mib:configure(Dir), + Config. + +finish_v3_inform(X) -> + finish_v2_inform(X). + + + +v2_inform_i(suite) -> []; +v2_inform_i(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + p("Testing inform sending from master agent... NOTE! This test\ntakes a " + "few minutes (5) to complete."), + MA = whereis(snmp_master_agent), + + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(ma_v2_inform1, [MA]), + + ?line unload_master("TestTrap"), + ?line unload_master("TestTrapv2"). + +v3_inform_i(X) -> v2_inform_i(X). + + +sa_error(suite) -> []; +sa_error(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing sa bad value (is_set_ok)..."), + try_test(sa_errs_bad_value), + + p("Testing sa gen err (set)..."), + try_test(sa_errs_gen_err), + + p("Testing too big..."), + try_test(sa_too_big), + + ?line unload_master("OLD-SNMPEA-MIB"), + stop_subagent(SA). + +sa_error_2(X) -> sa_error(X). + +sa_error_3(X) -> sa_error(X). + + +next_across_sa(suite) -> []; +next_across_sa(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Loading another subagent mib..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas1"]), + + rpc:call(SaNode, snmp, register_subagent, [MA, ?klas1, SA]), + try_test(load_test_sa), + + p("Testing next across subagent (endOfMibView from SA)..."), + try_test(next_across_sa), + + p("Unloading mib"), + snmpa:unload_mibs(SA, [MibDir ++ "Klas1"]), + rpc:call(SaNode, snmp, unregister_subagent, [MA, ?klas1]), + try_test(unreg_test), + + p("Starting another subagent"), + ?line {ok, SA2} = start_subagent(SaNode, ?klas1, "Klas1"), + p("Testing next across subagent (wrong prefix from SA)..."), + try_test(next_across_sa), + + stop_subagent(SA), + stop_subagent(SA2). + +next_across_sa_2(X) -> next_across_sa(X). + +next_across_sa_3(X) -> next_across_sa(X). + + +undo(suite) -> []; +undo(Config) when list(Config) -> + {SaNode, _MgrNode, MibDir} = init_case(Config), + MA = whereis(snmp_master_agent), + + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + + p("Testing undo phase at master agent..."), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(MA, [MibDir ++ "Klas4"]), + try_test(undo_test), + try_test(api_test2), + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas3"]), + + p("Testing bad return values from instrum. funcs..."), + try_test(bad_return), + + ?line ok = snmpa:unload_mibs(MA, [MibDir ++ "Klas4"]), + + p("Testing undo phase at subagent..."), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas3"]), + ?line ok = snmpa:load_mibs(SA, [MibDir ++ "Klas4"]), + ?line ok = snmpa:register_subagent(MA, ?klas3, SA), + ?line ok = snmpa:register_subagent(MA, ?klas4, SA), + try_test(undo_test), + try_test(api_test3), + + p("Testing undo phase across master/subagents..."), + try_test(undo_test), + try_test(api_test3), + stop_subagent(SA). + +undo_2(X) -> undo(X). + +undo_3(X) -> undo(X). + +%% Req. Test2 +v1_processing(suite) -> []; +v1_processing(Config) when list(Config) -> + ?DBG("v1_processing -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v1_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v2_processing(suite) -> []; +v2_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), + ?line unload_master("Test2"). + +%% Req. Test2 +v3_processing(suite) -> []; +v3_processing(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("Test2"), + try_test(v2_proc), % same as v2! + ?line unload_master("Test2"). + + +%% We'll try get/set/trap and inform for all the auth & priv protocols. +%% For informs, the mgr is auth-engine. The agent has to sync. This is +%% accomplished by the first inform sent. That one will generate a +%% report, which makes it in sync. The notification-generating +%% application times out, and send again. This time it'll work. +v3_security(suite) -> [v3_crypto_basic, v3_md5_auth, v3_sha_auth, v3_des_priv]. + +v3_crypto_basic(suite) -> []; +v3_crypto_basic(_Config) -> + EID = [0,0,0,0,0,0,0,0,0,0,0,2], + %% From rfc2274 appendix A.3.1 + ?line KMd5_1 = snmp:passwd2localized_key(md5, "maplesyrup", EID), + ?line [16#52,16#6f,16#5e,16#ed,16#9f,16#cc,16#e2,16#6f, + 16#89,16#64,16#c2,16#93,16#07,16#87,16#d8,16#2b] = + KMd5_1, + %% From rfc2274 appendix A.3.2 + ?line KSHA_1 = snmp:passwd2localized_key(sha, "maplesyrup", EID), + ?line [16#66,16#95,16#fe,16#bc,16#92,16#88,16#e3,16#62,16#82,16#23, + 16#5f,16#c7,16#15,16#1f,16#12,16#84,16#97,16#b3,16#8f,16#3f] = + KSHA_1, + %% From rfc2274, appendix A.5.1 + ?line KMd5_2 = snmp:passwd2localized_key(md5, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#88,16#05,16#61,16#51,16#41,16#67,16#6c,16#c9, + 16#19,16#61,16#74,16#e7,16#42,16#a3,16#25,16#51] = + snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + %% From rfc2274, appendix A.5.2 + ?line KSHA_2 = snmp:passwd2localized_key(sha, "newsyrup", EID), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#9c,16#10,16#17,16#f4, + 16#fd,16#48,16#3d,16#2d,16#e8,16#d5,16#fa,16#db, + 16#f8,16#43,16#92,16#cb,16#06,16#45,16#70,16#51] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2, 20, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + KSHA_1t = lists:sublist(KSHA_1, 16), + KSHA_2t = lists:sublist(KSHA_2, 16), + ?line [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00, + 16#7e,16#f8,16#d8,16#a4,16#c9,16#cd,16#b2,16#6b, + 16#47,16#59,16#1c,16#d8,16#52,16#ff,16#88,16#b5] = + snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1t, KSHA_2t, 16, + [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]), + + %% Try with correct random + ?line Kc1 = snmp_user_based_sm_mib:mk_key_change(md5, KMd5_1, KMd5_2), + ?line KMd5_2 = snmp_user_based_sm_mib:extract_new_key(md5, KMd5_1, Kc1), + ?line Kc2 = snmp_user_based_sm_mib:mk_key_change(sha, KSHA_1, KSHA_2), + ?line KSHA_2 = snmp_user_based_sm_mib:extract_new_key(sha, KSHA_1, Kc2), + ok. + + + +v3_md5_auth(suite) -> []; +v3_md5_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing MD5 authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authMD5"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_sha_auth(suite) -> []; +v3_sha_auth(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing SHA authentication...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authSHA"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +v3_des_priv(suite) -> []; +v3_des_priv(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + p("Testing DES encryption...takes a few seconds..."), + + AgentDir = ?config(agent_dir, Config), + ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv), + ?line snmp_target_mib:reconfigure(AgentDir), + + MA = whereis(snmp_master_agent), + + ?line load_master("Test2"), + ?line load_master("TestTrap"), + ?line load_master("TestTrapv2"), + + try_test(v3_sync, [[{v2_proc, []}, + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("TestTrapv2"), + ?line unload_master("TestTrap"), + ?line unload_master("Test2"), + ?line reset_target_params_conf(AgentDir). + +%% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). + +%% Make sure mgr is in sync with agent +v3_sync(Funcs) -> + ?DBG("v3_sync -> entry with Funcs: ~p",[Funcs]), + g([[sysDescr, 0]]), + expect(432, report, [{?usmStatsNotInTimeWindows_instance, any}]), + g([[sysDescr, 0]]), + expect(433, [{[sysDescr,0], any}]), + lists:foreach(fun({Func, Args}) -> apply(?MODULE, Func, Args) end, Funcs). + +v3_inform_sync(MA) -> + ?DBG("v3_sync -> entry with MA: ~p => Send notification",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, + "standard inform", []), + %% Make sure agent is in sync with mgr... + ?DBG("v3_sync -> wait some time: ",[]), + sleep(20000), % more than 1500*10 in target_addr.conf + ?DBG("v3_sync -> await response",[]), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]). + + +v2_caps(suite) -> []; +v2_caps(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + try_test(v2_caps_i, [node()]). + +v2_caps_3(X) -> v2_caps(X). + + +v2_caps_i(Node) -> + ?line Idx = rpc:call(Node, snmp, add_agent_caps, [[1,2,3,4,5], "test cap"]), + g([[sysORID, Idx], [sysORDescr, Idx]]), + ?line expect(1, [{[sysORID, Idx], [1,2,3,4,5]}, + {[sysORDescr, Idx], "test cap"}]), + ?line rpc:call(Node, snmp, del_agent_caps, [Idx]), + g([[sysORID, Idx]]), + ?line expect(2, [{[sysORID, Idx], noSuchInstance}]). + + +%% Req. Test2 +v1_proc() -> + ?DBG("v1_proc -> entry", []), + %% According to RFC1157. + %% Template: <Section>:<list no> + v1_get_p(), + v1_get_next_p(), + v1_set_p(). + + +v1_get_p() -> + %% 4.1.2:1 + g([[test2]]), + ?line expect(10, noSuchName, 1, [{[test2], 'NULL'}]), + g([[tDescr]]), + ?line expect(11, noSuchName, 1, [{[tDescr], 'NULL'}]), + g([[tDescr2,0]]), + ?line expect(12, noSuchName, 1, [{[tDescr2,0], 'NULL'}]), + g([[tDescr3,0]]), + ?line expect(131, noSuchName, 1, [{[tDescr3,0], 'NULL'}]), + g([[tDescr4,0]]), + ?line expect(132, noSuchName, 1, [{[tDescr4,0], 'NULL'}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(14, noSuchName, 2, [{[sysDescr, 0], 'NULL'}, + {[tDescr,0], 'NULL'}]), + g([[sysDescr,3]]), + ?line expect(15, noSuchName, 1, [{[sysDescr, 3], 'NULL'}]), + + %% 4.1.2:2 + g([[tTable]]), + ?line expect(20, noSuchName, 1, [{[tTable], 'NULL'}]), + g([[tEntry]]), + ?line expect(21, noSuchName, 1, [{[tEntry], 'NULL'}]), + + %% 4.1.2:3 + g([[tTooBig, 0]]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.2:4 + g([[tGenErr1, 0]]), + ?line expect(40, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(41, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(42, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]). + + +v1_get_next_p() -> + %% 4.1.3:1 + gn([[1,3,7,1]]), + ?line expect(10, noSuchName, 1, [{[1,3,7,1], 'NULL'}]), + gn([[tDescr2]]), + ?line expect(11, tooBig, 0, any), + + %% 4.1.3:2 + gn([[tTooBig]]), + io:format("We currently don't handle tooBig correct!!!\n"), +% ?line expect(20, tooBig, 0, [{[tTooBig], 'NULL'}]), + ?line expect(20, tooBig, 0, any), + + %% 4.1.3:3 + gn([[tGenErr1]]), +% ?line expect(40, genErr, 1, [{[tGenErr1], 'NULL'}]), + ?line expect(40, genErr, 1, any), + gn([[tGenErr2]]), +% ?line expect(41, genErr, 1, [{[tGenErr2], 'NULL'}]), + ?line expect(41, genErr, 1, any), + gn([[sysDescr], [tGenErr3]]), +% ?line expect(42, genErr, 2, [{[sysDescr], 'NULL'}, +% {[tGenErr3], 'NULL'}]). + ?line expect(42, genErr, 2, any). + +v1_set_p() -> + %% 4.1.5:1 + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noSuchName, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noSuchName, 1, [{[tDescr,0], "outside mibview"}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(12, noSuchName, 1, [{[tDescr3,0], "read-only"}]), + s([{[tDescr3], s, "noSuchObject"}]), + ?line expect(13, noSuchName, 1, [{[tDescr3], "noSuchObject"}]), + s([{[tDescr3,1], s, "noSuchInstance"}]), + ?line expect(14, noSuchName, 1, [{[tDescr3,1], "noSuchInstance"}]), + s([{[tDescr2,0], s, "inconsistentName"}]), + ?line expect(15, noSuchName, 1, [{[tDescr2,0], "inconsistentName"}]), + + %% 4.1.5:2 + s([{[tDescr2, 0], i, 4}]), + ?line expect(20, badValue, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(21, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.1.5:3 + %% The standard is quite incorrect here. The resp pdu was too big. In + %% the resp pdu, we have the original vbs. In the tooBig pdu we still + %% have to original vbs => the tooBig pdu is too big as well!!! It + %% may not get it to the manager, unless the agent uses 'NULL' instead + %% of the std-like original value. + s([{[tTooBig, 0], s, ?tooBigStr}]), + %% according to std: +% ?line expect(30, tooBig, 0, [{[tTooBig, 0], ?tooBigStr}]), + ?line expect(30, tooBig, 0, [{[tTooBig, 0], 'NULL'}]), + + %% 4.1.5:4 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(40, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]), + s([{[tDescr2, 0], s, "commit_fail"}]), + ?line expect(41, genErr, 1, [{[tDescr2, 0], "commit_fail"}]). + +%% Req. Test2 +v2_proc() -> + %% According to RFC1905. + %% Template: <Section>:<list no> + ?DBG("v2_proc -> entry",[]), + v2_get_p(), + v2_get_next_p(), + v2_get_bulk_p(), + v2_set_p(). + +v2_get_p() -> + %% 4.2.1:2 + ?DBG("v2_get_p -> entry",[]), + g([[test2]]), + ?line expect(10, [{[test2], noSuchObject}]), + g([[tDescr]]), + ?line expect(11, [{[tDescr], noSuchObject}]), + g([[tDescr4,0]]), + ?line expect(12, [{[tDescr4,0], noSuchObject}]), + g([[sysDescr, 0], [tDescr,0]]), % Outside mibview + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}, + {[tDescr,0], noSuchObject}]), + g([[tTable]]), + ?line expect(14, [{[tTable], noSuchObject}]), + g([[tEntry]]), + ?line expect(15, [{[tEntry], noSuchObject}]), + + %% 4.2.1:3 + g([[tDescr2,0]]), %% instrum ret noSuchName!!! + ?line expect(20, [{[tDescr2,0], noSuchInstance}]), + g([[tDescr3,0]]), + ?line expect(21, [{[tDescr3,0], noSuchInstance}]), + g([[sysDescr,3]]), + ?line expect(22, [{[sysDescr, 3], noSuchInstance}]), + g([[tIndex,1]]), + ?line expect(23, [{[tIndex, 1], noSuchInstance}]), + + %% 4.2.1 - any other error: genErr + g([[tGenErr1, 0]]), + ?line expect(30, genErr, 1, [{[tGenErr1, 0], 'NULL'}]), + g([[tGenErr2, 0]]), + ?line expect(31, genErr, 1, [{[tGenErr2, 0], 'NULL'}]), + g([[sysDescr, 0], [tGenErr3, 0]]), + ?line expect(32, genErr, 2, [{[sysDescr, 0], 'NULL'}, + {[tGenErr3, 0], 'NULL'}]), + + %% 4.2.1 - tooBig + g([[tTooBig, 0]]), + ?line expect(40, tooBig, 0, []). + + +v2_get_next_p() -> + %% 4.2.2:2 + ?DBG("v2_get_next_p -> entry",[]), + gn([[1,3,7,1]]), + ?line expect(10, [{[1,3,7,1], endOfMibView}]), + gn([[sysDescr], [1,3,7,1]]), + ?line expect(11, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gn([[tCnt2, 1]]), + ?line expect(12, [{[tCnt2,2], 100}]), + gn([[tCnt2, 2]]), + ?line expect(12, [{[tCnt2,2], endOfMibView}]), + + %% 4.2.2 - any other error: genErr + gn([[tGenErr1]]), + ?line expect(20, genErr, 1, [{[tGenErr1], 'NULL'}]), + gn([[tGenErr2]]), + ?line expect(21, genErr, 1, [{[tGenErr2], 'NULL'}]), + gn([[sysDescr], [tGenErr3]]), + ?line expect(22, genErr, 2, [{[sysDescr], 'NULL'}, + {[tGenErr3], 'NULL'}]), + + %% 4.2.2 - tooBig + gn([[tTooBig]]), + ?line expect(20, tooBig, 0, []). + +v2_get_bulk_p() -> + %% 4.2.3 + ?DBG("v2_get_bulk_p -> entry",[]), + gb(1, 1, []), + ?line expect(10, []), + gb(-1, 1, []), + ?line expect(11, []), + gb(-1, -1, []), + ?line expect(12, []), + gb(-1, -1, []), + ?line expect(13, []), + gb(2, 0, [[sysDescr], [1,3,7,1]]), + ?line expect(14, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(1, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(15, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}]), + gb(0, 2, [[sysDescr], [1,3,7,1]]), + ?line expect(16, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(2, 2, [[sysDescr], [1,3,7,1], [sysDescr], [1,3,7,1]]), + ?line expect(17, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysDescr, 0], "Erlang SNMP agent"}, + {[1,3,7,1], endOfMibView}, + {[sysObjectID, 0], [1,2,3]}, + {[1,3,7,1], endOfMibView}]), + + gb(1, 2, [[sysDescr], [sysDescr], [tTooBig]]), + ?line expect(18, [{[sysDescr, 0], "Erlang SNMP agent"}, + {[sysDescr, 0], "Erlang SNMP agent"}]), + + gb(1,12, [[tDescr2], [sysDescr]]), % next one after tDescr2 is tTooBig. + ?line expect(19, []), + + gb(2,2, [[sysDescr], [sysObjectID], [tGenErr1], [sysDescr]]), + ?line expect(20, genErr, 3, [{[sysDescr], 'NULL'}, + {[sysObjectID], 'NULL'}, + {[tGenErr1], 'NULL'}, + {[sysDescr], 'NULL'}]), + gb(0, 2, [[tCnt2, 1]]), + ?line expect(21, [{[tCnt2,2], 100}, + {[tCnt2,2], endOfMibView}]). + + +v2_set_p() -> + %% 4.2.5:1 + ?DBG("v2_set_p -> entry",[]), + s([{[1,3,7,0], i, 4}]), + ?line expect(10, noAccess, 1, [{[1,3,7,0], 4}]), + s([{[tDescr,0], s, "outside mibview"}]), + ?line expect(11, noAccess, 1, [{[tDescr,0], "outside mibview"}]), + + %% 4.2.5:2 + s([{[1,3,6,1,0], s, "noSuchObject"}]), + ?line expect(20, notWritable, 1, [{[1,3,6,1,0], "noSuchObject"}]), + + %% 4.2.5:3 + s([{[tDescr2, 0], i, 4}]), + ?line expect(30, wrongType, 1, [{[tDescr2, 0], 4}]), + s([{[tDescr2, 0], s, "badValue"}]), + ?line expect(31, badValue, 1, [{[tDescr2, 0], "badValue"}]), + + %% 4.2.5:4 + s([{[tStr, 0], s, ""}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], ""}]), + s([{[tStr, 0], s, "12345"}]), + ?line expect(40, wrongLength, 1, [{[tStr, 0], "12345"}]), + + %% 4.2.5:5 - N/A + + %% 4.2.5:6 + s([{[tInt1, 0], i, 0}]), + ?line expect(60, wrongValue, 1, [{[tInt1, 0], 0}]), + s([{[tInt1, 0], i, 5}]), + ?line expect(61, wrongValue, 1, [{[tInt1, 0], 5}]), + s([{[tInt2, 0], i, 0}]), + ?line expect(62, wrongValue, 1, [{[tInt2, 0], 0}]), + s([{[tInt2, 0], i, 5}]), + ?line expect(63, wrongValue, 1, [{[tInt2, 0], 5}]), + s([{[tInt3, 0], i, 5}]), + ?line expect(64, wrongValue, 1, [{[tInt3, 0], 5}]), + + %% 4.2.5:7 + s([{[tDescrX, 1, 1], s, "noCreation"}]), + ?line expect(70, noCreation, 1, [{[tDescrX, 1, 1], "noCreation"}]), + + %% 4.2.5:8 + s([{[tDescrX, 1, 2], s, "inconsistentName"}]), + ?line expect(80, inconsistentName, 1, + [{[tDescrX, 1, 2], "inconsistentName"}]), + + %% 4.2.5:9 + s([{[tCnt, 1, 2], i, 5}]), + ?line expect(90, notWritable, 1, [{[tCnt, 1, 2], 5}]), + s([{[tDescr3,0], s, "read-only"}]), + ?line expect(90, notWritable, 1, [{[tDescr3,0], "read-only"}]), + + %% 4.2.5:10 + s([{[tDescr2,0], s, "inconsistentValue"}]), + ?line expect(100, inconsistentValue, 1, + [{[tDescr2,0], "inconsistentValue"}]), + + %% 4.2.5:11 + s([{[tDescr2,0], s, "resourceUnavailable"}]), + ?line expect(110, resourceUnavailable, 1, + [{[tDescr2,0],"resourceUnavailable"}]), + + %% 4.2.5:12 + s([{[tDescr2, 0], s, "is_set_ok_fail"}]), + ?line expect(120, genErr, 1, [{[tDescr2, 0], "is_set_ok_fail"}]). + + %% commitFailed and undoFailed is tested by the 'undo' case. + + +%% Req. OLD-SNMPEA-MIB +table_test() -> + io:format("Testing simple get, next and set on communityTable...~n"), +%% {[147,214,36,45], "public", 2, readWrite}. +%% {[147,214,36,45], "standard trap", 2, read}. + Key1c3 = [intCommunityViewIndex,get(mip),is("public")], + Key2c3 = [intCommunityViewIndex,get(mip),is("standard trap")], + Key1c4 = [intCommunityAccess,get(mip),is("public")], + EndKey = [intCommunityEntry,[9],get(mip),is("public")], + gn([[intCommunityEntry]]), + ?line expect(7, [{Key1c3, 2}]), + gn([[intCommunityTable]]), + ?line expect(71, [{Key1c3, 2}]), + gn([[community]]), + ?line expect(72, [{Key1c3, 2}]), + gn([[otpSnmpeaMIB]]), + ?line expect(73, [{Key1c3, 2}]), + gn([[ericsson]]), + ?line expect(74, [{Key1c3, 2}]), + gn([Key1c3]), + ?line expect(8, [{Key2c3, 2}]), + gn([Key2c3]), + ?line expect(9, [{Key1c4, 2}]), + gn([EndKey]), + AgentIp = [intAgentIpAddress,0], + ?line expect(10, [{AgentIp, any}]), + g([Key1c3]), + ?line expect(11, [{Key1c3, 2}]), + g([EndKey]), + ?line ?v1_2(expect(12, noSuchName, 1, any), + expect(12, [{EndKey, noSuchObject}])), + + io:format("Testing row creation/deletion on communityTable...~n"), + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + s([{NewKeyc5, ?createAndGo}]), + ?line expect(14, ?v1_2(badValue, inconsistentValue), 1,any), + s([{NewKeyc5, ?createAndGo}, {NewKeyc3, 2}, {NewKeyc4, 2}]), + ?line expect(15, [{NewKeyc5, ?createAndGo},{NewKeyc3, 2}, {NewKeyc4, 2}]), + g([NewKeyc4]), + ?line expect(16, [{NewKeyc4, 2}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(17, [{NewKeyc5, ?destroy}]), + s([{NewKeyc4, 2}]), + ?line expect(18, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc4, 2}]), + s([{NewKeyc5, ?createAndWait}]), + ?line expect(19, [{NewKeyc5, ?createAndWait}]), + g([NewKeyc5]), + ?line expect(20, [{NewKeyc5, ?notReady}]), + s([{NewKeyc4, 2}]), + ?line expect(21, [{NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(22, [{NewKeyc5, ?notReady}]), + s([{NewKeyc3, 2}]), + ?line expect(23, [{NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(24, [{NewKeyc5, ?notInService}]), + s([{NewKeyc5, ?active}]), + ?line expect(25, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(26, [{NewKeyc5, ?destroy}]), + s([{NewKeyc3, 3}]), + ?line expect(27, ?v1_2(noSuchName, inconsistentName), 1,[{NewKeyc3, 3}]), + otp_1128(). + +%% Req. system group +simple_standard_test() -> + ?DBG("simple_standard_test -> entry",[]), + gn([[1,1]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3]]), + ?line expect(11, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6]]), + ?line expect(12, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1]]), + ?line expect(13, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2]]), + ?line expect(14, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1]]), + ?line expect(15, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[1,3,6,1,2,1,1]]), + ?line expect(16, [{[sysDescr,0], "Erlang SNMP agent"}]), + gn([[sysDescr]]), + ?line expect(17, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr,0]]), + ?line expect(2, [{[sysDescr,0], "Erlang SNMP agent"}]), + g([[sysDescr]]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{[sysDescr], noSuchObject}])), + g([[1,6,7,0]]), + ?line ?v1_2(expect(41, noSuchName, 1, any), + expect(3, [{[1,6,7,0], noSuchObject}])), + gn([[1,13]]), + ?line ?v1_2(expect(4, noSuchName,1, any), + expect(4, [{[1,13], endOfMibView}])), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + g([[sysLocation, 0]]), + ?line expect(6, [{[sysLocation, 0], "new_value"}]), + io:format("Testing noSuchName and badValue...~n"), + s([{[sysServices,0], 3}]), + ?line expect(61, ?v1_2(noSuchName, notWritable), 1, any), + s([{[sysLocation, 0], i, 3}]), + ?line expect(62, ?v1_2(badValue, wrongType), 1, any), + ?DBG("simple_standard_test -> done",[]), + ok. + +%% This is run in the agent node +db_notify_client(suite) -> []; +db_notify_client(Config) when list(Config) -> + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("~n\tSaNode: ~p~n\tMgrNode: ~p~n\tMibDir: ~p", + [SaNode,MgrNode,MibDir]), + snmpa_local_db:register_notify_client(self(),?MODULE), + + %% This call (the manager) will issue to set operations, so + %% we expect to receive to notify(insert) calls. + try_test(db_notify_client_test), + + ?DBG("await first notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("first notify received",[]),ok + end, + + ?DBG("await second notify",[]), + receive + {db_notify_test_reply,insert} -> ?DBG("second notify received",[]),ok + end, + + snmpa_local_db:unregister_notify_client(self()). + + +%% This is run in the manager node +db_notify_client_test() -> + ?DBG("set first new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]), + + ?DBG("set second new sysLocation",[]), + s([{[sysLocation, 0], "new_value"}]), + ?line expect(5, [{[sysLocation, 0], "new_value"}]). + +notify(Pid,What) -> + ?DBG("notify(~p,~p) -> called",[Pid,What]), + Pid ! {db_notify_test_reply,What}. + + +%% Req: system group, OLD-SNMPEA-MIB, Klas1 +big_test() -> + ?DBG("big_test -> testing simple next/get/set @ master agent...",[]), + simple_standard_test(), + + ?DBG("big_test -> testing simple next/get/set @ subagent...",[]), + gn([[klas1]]), + ?line expect(1, [{[fname,0], ""}]), + g([[fname,0]]), + ?line expect(2, [{[fname,0], ""}]), + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[fname,0]]), + ?line expect(4, [{[fname,0], "test set"}]), + + ?DBG("big_test -> " + "testing next from last instance in master to subagent...",[]), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname,0], "test set"}]), + s([{[fname,0], s, ""}]), + ?line expect(52, [{[fname,0], ""}]), + + table_test(), + + ?DBG("big_test -> adding one row in subagent table",[]), + _FTab = [friendsEntry], + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {[friendsEntry, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [friendsEntry, [3, 3]]]), + ?line expect(7, [{[friendsEntry, [2, 3]], "kompis3"}, + {[friendsEntry, [3, 3]], ?active}]), + s([{[friendsEntry, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry, [3, 3]], ?destroy}]), + + otp_1131(), + + ?DBG("big_test -> adding two rows in subagent table with special INDEX", + []), + s([{[kompissEntry, [1, 3]], s, "kompis3"}, + {[kompissEntry, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?createAndGo}]), + g([[kompissEntry, [1, 3]], + [kompissEntry, [2, 3]]]), + ?line expect(10, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + gn([[kompissEntry, [1]], + [kompissEntry, [2]]]), + ?line expect(11, [{[kompissEntry, [1, 3]], "kompis3"}, + {[kompissEntry, [2, 3]], ?active}]), + s([{[kompissEntry, [1, 2]], s, "kompis3"}, + {[kompissEntry, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?createAndGo}]), + gn([[kompissEntry, [1, 1]], + [kompissEntry, [2, 1]]]), + ?line expect(13, [{[kompissEntry, [1, 2]], "kompis3"}, + {[kompissEntry, [2, 2]], ?active}]), + s([{[kompissEntry, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry, [2, 3]], ?destroy}]), + s([{[kompissEntry, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry, [2, 2]], ?destroy}]), + ?DBG("big_test -> done",[]), + ok. + +%% Req. system group, Klas2, OLD-SNMPEA-MIB +big_test_2() -> + p("Testing simple next/get/set @ master agent (2)..."), + simple_standard_test(), + + p("Testing simple next/get/set @ subagent (2)..."), + gn([[klas2]]), + ?line expect(1, [{[fname2,0], ""}]), + g([[fname2,0]]), + ?line expect(2, [{[fname2,0], ""}]), + s([{[fname2,0], s, "test set"}]), + ?line expect(3, [{[fname2,0], "test set"}]), + g([[fname2,0]]), + ?line expect(4, [{[fname2,0], "test set"}]), + + otp_1298(), + + p("Testing next from last object in master to subagent (2)..."), + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(5, [{[fname2,0], "test set"}]), + gn([[1,1], + [?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(51, [{[sysDescr,0], "Erlang SNMP agent"}, + {[fname2,0], "test set"}]), + + table_test(), + + p("Adding one row in subagent table (2)"), + _FTab = [friendsEntry2], + s([{[friendsEntry2, [2, 3]], s, "kompis3"}, + {[friendsEntry2, [3, 3]], i, ?createAndGo}]), + ?line expect(6, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?createAndGo}]), + g([[friendsEntry2, [2, 3]], + [friendsEntry2, [3, 3]]]), + ?line expect(7, [{[friendsEntry2, [2, 3]], "kompis3"}, + {[friendsEntry2, [3, 3]], ?active}]), + s([{[friendsEntry2, [3, 3]], i, ?destroy}]), + ?line expect(8, [{[friendsEntry2, [3, 3]], ?destroy}]), + + p("Adding two rows in subagent table with special INDEX (2)"), + s([{[kompissEntry2, [1, 3]], s, "kompis3"}, + {[kompissEntry2, [2, 3]], i, ?createAndGo}]), + ?line expect(9, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?createAndGo}]), + g([[kompissEntry2, [1, 3]], + [kompissEntry2, [2, 3]]]), + ?line expect(10, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + gn([[kompissEntry2, [1]], + [kompissEntry2, [2]]]), + ?line expect(11, [{[kompissEntry2, [1, 3]], "kompis3"}, + {[kompissEntry2, [2, 3]], ?active}]), + s([{[kompissEntry2, [1, 2]], s, "kompis3"}, + {[kompissEntry2, [2, 2]], i, ?createAndGo}]), + ?line expect(12, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?createAndGo}]), + gn([[kompissEntry2, [1, 1]], + [kompissEntry2, [2, 1]]]), + ?line expect(13, [{[kompissEntry2, [1, 2]], "kompis3"}, + {[kompissEntry2, [2, 2]], ?active}]), + s([{[kompissEntry2, [2, 3]], i, ?destroy}]), + ?line expect(14, [{[kompissEntry2, [2, 3]], ?destroy}]), + s([{[kompissEntry2, [2, 2]], i, ?destroy}]), + ?line expect(15, [{[kompissEntry2, [2, 2]], ?destroy}]), + ok. + +%% Req. Test1 +multi_threaded_test() -> + p("Testing multi threaded agent..."), + g([[multiStr,0]]), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(1, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "pelle"}]), + ?line expect(2, [{[sysLocation, 0], "pelle"}]), + Pid ! continue, + ?line expect(3, [{[multiStr,0], "ok"}]), + + s([{[multiStr, 0], s, "block"}]), + Pid2 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(4, [{[sysUpTime,0], any}]), + g([[multiStr,0]]), + Pid3 = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(5, [{[sysUpTime,0], any}]), + s([{[sysLocation, 0], s, "kalle"}]), + Pid3 ! continue, + ?line expect(6, [{[multiStr,0], "ok"}]), + Pid2 ! continue, + ?line expect(7, [{[multiStr,0], "block"}]), + ?line expect(8, [{[sysLocation,0], "kalle"}]). + +%% Req. Test1, TestTrapv2 +mt_trap_test(MA) -> + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + snmpa:send_trap(MA, mtTrap, "standard trap"), + Pid = get_multi_pid(), + g([[sysUpTime,0]]), + ?line expect(2, [{[sysUpTime,0], any}]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + Pid ! continue, + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [2]}, + {[multiStr,0], "ok"}]). + + +get_multi_pid() -> + get_multi_pid(10). +get_multi_pid(0) -> + ?line ?FAIL(no_global_name); +get_multi_pid(N) -> + sleep(1000), + case global:whereis_name(snmp_multi_tester) of + Pid when pid(Pid) -> Pid; + _ -> get_multi_pid(N-1) + end. + +%% Req. Test1 +types_v2_test() -> + p("Testing v2 types..."), + + s([{[bits1,0], 2#10}]), + ?line expect(1, [{[bits1,0], ?str(2#10)}]), + g([[bits1,0]]), + ?line expect(2, [{[bits1,0], ?str(2#101)}]), + + s([{[bits2,0], 2#11000000110}]), + ?line expect(3, [{[bits2,0], ?str(2#11000000110)}]), + g([[bits2,0]]), + ?line expect(4, [{[bits2,0], ?str(2#11000000110)}]), + + g([[bits3,0]]), + ?line expect(50, genErr, 1, any), + + g([[bits4,0]]), + ?line expect(51, genErr, 1, any), + + s([{[bits1,0], s, [2#10]}]), + ?line expect(6, ?v1_2(badValue, wrongValue), 1, any), + + s([{[bits2,0], 2#11001001101010011}]), + ?line expect(7, ?v1_2(badValue, wrongValue), 1, any). + + +%% Req. Test1 +implied_test(MA) -> + ?LOG("implied_test -> start",[]), + p("Testing IMPLIED..."), + + snmpa:verbosity(MA,trace), + snmpa:verbosity(MA,trace), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = "apa", + Idx2 = "qq", + ?DBG("implied_test -> (send) create row 1 '~s' in table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?createAndGo}, {[testDescr, Idx1],s,"row 1"}]), + ?line expect(1, [{[testStatus, Idx1], ?createAndGo}, + {[testDescr, Idx1], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?createAndGo}, {[testDescr, Idx2],s,"row 2"}]), + ?line expect(2, [{[testStatus, Idx2], ?createAndGo}, + {[testDescr, Idx2], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr)",[]), + gn([[testDescr]]), + ?line expect(3, [{[testDescr,Idx1], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr) of row 1",[]), + gn([[testDescr,Idx1]]), + ?line expect(4, [{[testDescr,Idx2], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 1",[Idx1]), + s([{[testStatus, Idx1], i, ?destroy}]), + ?line expect(5, [{[testStatus, Idx1], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 1",[Idx2]), + s([{[testStatus, Idx2], i, ?destroy}]), + ?line expect(6, [{[testStatus, Idx2], ?destroy}]), + + %% Try the same in other table + Idx3 = [1, "apa"], + Idx4 = [1, "qq"], + ?DBG("implied_test -> (send) create row 1 '~s' in table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?createAndGo}, {[testDescr2,Idx3],s,"row 1"}]), + ?line expect(1, [{[testStatus2, Idx3], ?createAndGo}, + {[testDescr2, Idx3], "row 1"}]), + ?DBG("implied_test -> (send) create row 2 '~s' in table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?createAndGo}, {[testDescr2,Idx4],s,"row 2"}]), + ?line expect(2, [{[testStatus2, Idx4], ?createAndGo}, + {[testDescr2, Idx4], "row 2"}]), + ?DBG("implied_test -> get-next(testDescr2)",[]), + gn([[testDescr2]]), + ?line expect(3, [{[testDescr2,Idx3], "row 1"}]), + ?DBG("implied_test -> get-next(testDescr2) of row 1",[]), + gn([[testDescr2,Idx3]]), + ?line expect(4, [{[testDescr2,Idx4], "row 2"}]), + + % Delete the rows + ?DBG("implied_test -> (send) delete row 1 '~s' from table 2",[Idx3]), + s([{[testStatus2, Idx3], i, ?destroy}]), + ?line expect(5, [{[testStatus2, Idx3], ?destroy}]), + ?DBG("implied_test -> (send) delete row 2 '~s' from table 2",[Idx4]), + s([{[testStatus2, Idx4], i, ?destroy}]), + ?line expect(6, [{[testStatus2, Idx4], ?destroy}]), + + snmpa:verbosity(MA,log), + + ?LOG("implied_test -> done",[]). + + + +%% Req. Test1 +sparse_table_test() -> + p("Testing sparse table..."), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + s([{[sparseStatus, Idx1], i, ?createAndGo}, + {[sparseDescr, Idx1], s, "row 1"}]), + ?line expect(1, [{[sparseStatus, Idx1], ?createAndGo}, + {[sparseDescr, Idx1], "row 1"}]), + s([{[sparseStatus, Idx2], i, ?createAndGo}, + {[sparseDescr, Idx2], s, "row 2"}]), + ?line expect(2, [{[sparseStatus, Idx2], ?createAndGo}, + {[sparseDescr, Idx2], "row 2"}]), + ?v1_2(gn([[sparseIndex], [sparseDescr,Idx1], [sparseDescr,Idx2], + [sparseStatus,Idx1], [sparseStatus,Idx2]]), + gb(0,5,[[sparseIndex]])), + ?line expect(3, [{[sparseDescr,Idx1], "row 1"}, + {[sparseDescr,Idx2], "row 2"}, + {[sparseStatus,Idx1], ?active}, + {[sparseStatus,Idx2], ?active}, + {[sparseStr,0], "slut"}]), + % Delete the rows + s([{[sparseStatus, Idx1], i, ?destroy}]), + ?line expect(4, [{[sparseStatus, Idx1], ?destroy}]), + s([{[sparseStatus, Idx2], i, ?destroy}]), + ?line expect(5, [{[sparseStatus, Idx2], ?destroy}]). + + +%% Req. Test1 +cnt_64_test(MA) -> + ?LOG("start cnt64 test (~p)",[MA]), + snmpa:verbosity(MA,trace), + ?LOG("start cnt64 test",[]), + p("Testing Counter64, and at the same time, RowStatus is not last column"), + + ?DBG("get cnt64",[]), + g([[cnt64,0]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(1, noSuchName, 1, any), + expect(1, [{[cnt64,0],18446744073709551615}])), + ?DBG("get-next cnt64",[]), + gn([[cnt64]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(2, [{[cnt64Str,0], "after cnt64"}]), + expect(2, [{[cnt64,0],18446744073709551615}])), + ?DBG("send cntTrap",[]), + snmpa:send_trap(MA,cntTrap,"standard trap",[{sysContact,"pelle"}, + {cnt64, 10}, + {sysLocation, "here"}]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, trap, [test], 6, 1, [{[sysContact,0], "pelle"}, + {[sysLocation,0], "here"}]), + expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?testTrap ++ [1]}, + {[sysContact,0], "pelle"}, + {[cnt64,0], 10}, + {[sysLocation,0], "here"}])), + + %% Create two rows, check that they are get-nexted in correct order. + Idx1 = 1, + Idx2 = 2, + ?DBG("create row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(1, [{[cntStatus, Idx1], ?createAndGo}]), + ?DBG("create row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?createAndGo}]), + ?DBG("await response",[]), + ?line expect(2, [{[cntStatus, Idx2], ?createAndGo}]), + + ?DBG("get-next (cntIndex)",[]), + gn([[cntIndex]]), + ?DBG("await response",[]), + ?line ?v1_2(expect(3, [{[cntStatus,Idx1], ?active}]), + expect(3, [{[cntCnt,Idx1], 0}])), + % Delete the rows + ?DBG("delete row (cntStatus): ~p",[Idx1]), + s([{[cntStatus, Idx1], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(4, [{[cntStatus, Idx1], ?destroy}]), + ?DBG("delete row (cntStatus): ~p",[Idx2]), + s([{[cntStatus, Idx2], i, ?destroy}]), + ?DBG("await response",[]), + ?line expect(5, [{[cntStatus, Idx2], ?destroy}]), + catch snmpa:verbosity(MA,log), + ?DBG("done",[]), + ok. + +%% Req. Test1 +opaque_test() -> + p("Testing Opaque datatype..."), + g([[opaqueObj,0]]), + ?line expect(1, [{[opaqueObj,0], "opaque-data"}]). + +%% Req. OLD-SNMPEA-MIB +api_test(MaNode) -> + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [intAgentIpAddress]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, + oid_to_name, [OID]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [[1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, [intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, + int_to_enum, ['RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, + enum_to_int, ['xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, ['xxRowStatus', 1]), + ?line case snmp:date_and_time() of + List when list(List), length(List) == 8 -> ok; + List when list(List), length(List) == 11 -> ok + end. + +%% Req. Klas3 +api_test2() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]), + g([[fname4,0]]), + ?line expect(2, [{[fname4,0], 1}]). + +api_test3() -> + g([[fname3,0]]), + ?line expect(1, [{[fname3,0], "ok"}]). + + +unreg_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[snmpInPkts, 0], any}]). + +load_test() -> + gn([[?v1_2(sysServices, sysORLastChange),0]]), + ?line expect(1, [{[fname,0], ""}]). + +%% Req. Klas1 +load_test_sa() -> + gn([[?v1_2(sysServices,sysORLastChange), 0]]), + ?line expect(1, [{[fname,0], any}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_get() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0], Key1c4, [fname,0],Key1c3, + [sysName,0]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,0], "test"}]), + g([[1,3,7,1], Key1c4, [sysDescr,0], [1,3,7,2], Key1c3, [sysDescr,0]]), + ?line ?v1_2(expect(2, noSuchName, [1,4], any), + expect(2, [{[1,3,7,1], noSuchObject}, + {Key1c4, 2}, + {[sysDescr,0], "Erlang SNMP agent"}, + {[1,3,7,2], noSuchObject}, + {Key1c3, 2}, + {[sysDescr,0], "Erlang SNMP agent"}])). + +%% Req. v1, system group, Klas1, OLD-SNMPEA-MIB, *ej* Klas3. +do_mul_get_err() -> + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + g([[sysDescr,0],Key1c4,[fname,0], Key1c3, [sysName,2]]), + ?line ?v1_2(expect(1, noSuchName, 5, any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname,0], "test set"}, + {Key1c3, 2}, + {[sysName,2], noSuchInstance}])), + g([[sysDescr,0],Key1c4,[fname3,0], Key1c3, [sysName,1]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[fname3,0], noSuchObject}, + {Key1c3, 2}, + {[sysName,1], noSuchInstance}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [fname],Key1c3s,[sysName]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, {[fname,0], "test set"}, + {Key1c3, 2}, {[sysName,0], "test"}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_next_err() -> + Key1c3s = [intCommunityEntry,[3],get(mip),is("publi")], + Key1c4s = [intCommunityEntry,[4],get(mip),is("publi")], + Key1c3 = [intCommunityEntry,[3],get(mip),is("public")], + Key1c4 = [intCommunityEntry,[4],get(mip),is("public")], + s([{[fname,0], s, "test set"}]), + ?line expect(3, [{[fname,0], "test set"}]), + gn([[sysDescr], Key1c4s, [1,3,6,999], [fname],[1,3,90], Key1c3s,[sysName]]), + ?line ?v1_2(expect(1, noSuchName, [3,5], any), + expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {Key1c4, 2}, + {[1,3,6,999], endOfMibView}, + {[fname,0], "test set"}, + {[1,3,90], endOfMibView}, + {Key1c3, 2}, + {[sysName,0], "test"}])). + + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set() -> + p("Adding one row in subagent table, and one in master table"), + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, [{[friendsEntry, [2, 3]], "kompis3"}, + {NewKeyc3, 2}, + {[sysLocation,0], "new_value"}, + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + g([[friendsEntry, [2, 3]], + [sysLocation,0], + [friendsEntry, [3, 3]]]), + ?line expect(2, [{[friendsEntry, [2, 3]], "kompis3"}, + {[sysLocation,0], "new_value"}, + {[friendsEntry, [3, 3]], ?active}]), + g([NewKeyc4]), + ?line expect(3, [{NewKeyc4, 2}]), + s([{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]), + ?line expect(4, [{[friendsEntry, [3, 3]], ?destroy}, + {NewKeyc5, ?destroy}]). + +%% Req. system group, Klas1, OLD-SNMPEA-MIB +do_mul_set_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + p("Adding one row in subagent table, and one in master table"), + s([{[friendsEntry, [2, 3]], s, "kompis3"}, + {NewKeyc3, 2}, + {[sysUpTime,0], 45}, % sysUpTime (readOnly) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}, + {[friendsEntry, [3, 3]], ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, notWritable), 3, any), + g([[friendsEntry, [2, 3]]]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{[friendsEntry, [2,3]], noSuchInstance}])), + g([NewKeyc4]), + ?line ?v1_2(expect(3, noSuchName, 1, any), + expect(3, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB +sa_mib() -> + g([[sa, [2,0]]]), + ?line expect(1, [{[sa, [2,0]], 3}]), + s([{[sa, [1,0]], s, "sa_test"}]), + ?line expect(2, [{[sa, [1,0]], "sa_test"}]). + +ma_trap1(MA) -> + snmpa:send_trap(MA, testTrap2, "standard trap"), + ?line expect(1, trap, [system], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]), + snmpa:send_trap(MA, testTrap1, "standard trap"), + ?line expect(2, trap, [1,2,3] , 1, 0, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}]). + +ma_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, trap, [system], 6, 1, [{[system, [4,0]], "pelle"}]). + +ma_v2_2_v1_trap2(MA) -> + snmpa:send_trap(MA,linkUp,"standard trap",[{ifIndex, [1], 1}, + {ifAdminStatus, [1], 1}, + {ifOperStatus, [1], 2}]), + ?line expect(3, trap, [1,2,3], 3, 0, [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}]). + +sa_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, trap, [ericsson], 6, 1, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(5, trap, [ericsson], 6, 1, [{[system, [4,0]], + "pelle"}, + {[sa, [1,0]], "sa_test"}]). + +sa_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(6, trap, [ericsson], 6, 2, [{[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}]). + +ma_v2_trap1(MA) -> + ?DBG("ma_v2_traps -> entry with MA = ~p => " + "send standard trap: testTrapv22",[MA]), + snmpa:send_trap(MA, testTrapv22, "standard trap"), + ?line expect(1, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_traps -> send standard trap: testTrapv21",[]), + snmpa:send_trap(MA, testTrapv21, "standard trap"), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmp ++ [1]}]). + +ma_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrapv22,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}]). + +%% Note: This test case takes a while... actually a couple of minutes. +ma_v2_inform1(MA) -> + ?DBG("ma_v2_inform -> entry with MA = ~p => " + "send notification: testTrapv22",[MA]), + ?line snmpa:send_notification(MA, testTrapv22, no_receiver, "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag1, self()}, + "standard inform", []), + ?line expect(1, {inform, true}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag1, [_]} -> + ok; + {snmp_targets, tag1, Addrs1} -> + ?line ?FAIL({bad_addrs, Addrs1}) + after + 5000 -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag1, {got_response, _}} -> + ok; + {snmp_notification, tag1, {no_response, _}} -> + ?line ?FAIL(no_response) + after + 20000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag1) timeout",[]), + ?line ?FAIL(nothing_at_all) + end, + + %% + %% -- The rest is possibly erroneous... + %% + + ?DBG("ma_v2_inform -> send notification: testTrapv22",[]), + snmpa:send_notification(MA, testTrapv22, {tag2, self()}, + "standard inform", []), + ?line expect(2, {inform, false}, + [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}]), + ?DBG("ma_v2_inform -> await targets",[]), + receive + {snmp_targets, tag2, [_]} -> + ok; + {snmp_targets, tag2, Addrs2} -> + ?ERR("ma_v2_inform1 -> awaiting snmp_targets(tag2) timeout",[]), + ?line ?FAIL({bad_addrs, Addrs2}) + after + 5000 -> + ?line ?FAIL(nothing_at_all) + end, + ?DBG("ma_v2_inform -> await notification",[]), + receive + {snmp_notification, tag2, {got_response, _}} -> + ?line ?FAIL(got_response); + {snmp_notification, tag2, {no_response, _}} -> + ok + after + 240000 -> + ?ERR("ma_v2_inform1 -> " + "awaiting snmp_notification(tag2) timeout",[]), + ?line ?FAIL(nothing_at_all) + end. + + +ma_v1_2_v2_trap(MA) -> + snmpa:send_trap(MA,linkDown,"standard trap",[{ifIndex, [1], 1}]), + ?line expect(2, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?snmpTraps ++ [3]}, + {[ifIndex, 1], 1}, + {[snmpTrapEnterprise, 0], [1,2,3]}]). + + +ma_v1_2_v2_trap2(MA) -> + snmpa:send_trap(MA,testTrap2,"standard trap",[{sysContact,"pelle"}]), + ?line expect(3, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}, + {[system, [4,0]], "pelle"}, + {[snmpTrapEnterprise, 0], ?system}]). + + +sa_v1_2_v2_trap1(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap"), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + +sa_v1_2_v2_trap2(SA) -> + snmpa:send_trap(SA, saTrap, "standard trap",[{sysContact,"pelle"}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 1]}, + {[system, [4,0]], "pelle"}, + {[sa, [1,0]], "sa_test"}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +sa_v1_2_v2_trap3(SA) -> + snmpa:send_trap(SA, saTrap2, "standard trap", + [{intViewSubtree, [4], [1,2,3,4]}]), + ?line expect(4, v2trap, [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?ericsson ++ [0, 2]}, + {[system, [4,0]], + "{mbj,eklas}@erlang.ericsson.se"}, + {[sa, [1,0]], "sa_test"}, + {[intViewSubtree,4],[1,2,3,4]}, + {[snmpTrapEnterprise, 0], ?ericsson}]). + + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_bad_value() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2}, + {[sa, [2,0]], 5}, % badValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, badValue, 2, any), + s([{NewKeyc3, 2}, + {[sa, [2,0]], 6}, % wrongValue (i is_set_ok) + {NewKeyc5, ?createAndGo}, + {NewKeyc4, 2}]), + ?line expect(1, ?v1_2(badValue, wrongValue), 2, any), + g([NewKeyc4]), + ?line ?v1_2(expect(2, noSuchName, 1, any), + expect(2, [{NewKeyc4, noSuchInstance}])). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_errs_gen_err() -> + NewKeyc3 = [intCommunityEntry,[3],get(mip),is("test")], + NewKeyc4 = [intCommunityEntry,[4],get(mip),is("test")], + NewKeyc5 = [intCommunityEntry,[5],get(mip),is("test")], + s([{NewKeyc3, 2},{NewKeyc4, 2}, + {NewKeyc5, ?createAndGo}, {[sa, [3,0]], 5}]), + ?line expect(1, genErr, 4, any), +% The row might have been added; we don't know. +% (as a matter of fact we do - it is added, because the agent +% first sets its own vars, and then th SAs. Lets destroy it. + s([{NewKeyc5, ?destroy}]), + ?line expect(2, [{NewKeyc5, ?destroy}]). + +%% Req. SA-MIB, OLD-SNMPEA-MIB +sa_too_big() -> + g([[sa, [4,0]]]), + ?line expect(1, tooBig). + +%% Req. Klas1, system group, snmp group (v1/v2) +next_across_sa() -> + gn([[sysDescr],[klas1,5]]), + ?line expect(1, [{[sysDescr,0], "Erlang SNMP agent"}, + {[snmpInPkts, 0], any}]). + +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]). -> noError +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]). -> {badValue, 2} +%% snmp_test_mgr:s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]). -> {genErr, 1} +%% snmp_test_mgr:s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]). -> {genErr, 2} +%% Req. Klas3, Klas4 +undo_test() -> + s([{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + ?line expect(1, [{[fStatus3, 1], 4}, {[fname3,0], "ok"}]), + s([{[fStatus3, 1], 4}, {[fname3,0], "hoj"}]), + ?line expect(2, ?v1_2(badValue, inconsistentValue), 2, any), + s([{[fStatus3, 3], 4}, {[fname3,0], "hoj"}]), + ?line expect(3, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 4], 4}, {[fname3,0], "ok"}]), + ?line expect(4, ?v1_2(genErr, commitFailed), 1, any), +% unfortunatly we don't know if we'll get undoFailed or commitFailed. +% it depends on which order the agent traverses the varbind list. +% s([{[fStatus3, 4], 4}, {[fname3,0], "ufail"}]), +% ?line expect(5, ?v1_2(genErr, undoFailed), 1, any), + s([{[fStatus3, 1], 4}, {[fname3,0], "xfail"}]), + ?line expect(6, genErr, 2, any). + +%% Req. Klas3, Klas4 +bad_return() -> + g([[fStatus4,4], + [fName4,4]]), + ?line expect(4, genErr, 2, any), + g([[fStatus4,5], + [fName4,5]]), + ?line expect(5, genErr, 1, any), + g([[fStatus4,6], + [fName4,6]]), + ?line expect(6, genErr, 2, any), + gn([[fStatus4,7], + [fName4,7]]), + ?line expect(7, genErr, 2, any), + gn([[fStatus4,8], + [fName4,8]]), + ?line expect(8, genErr, 1, any), + gn([[fStatus4,9], + [fName4,9]]), + ?line expect(9, genErr, 2, any). + + +%%%----------------------------------------------------------------- +%%% Test the implementation of standard mibs. +%%% We should *at least* try to GET all variables, just to make +%%% sure the instrumentation functions work. +%%% Note that many of the functions in the standard mib is +%%% already tested by the normal tests. +%%%----------------------------------------------------------------- +standard_mibs(suite) -> + [snmp_standard_mib, snmp_community_mib, + snmp_framework_mib, + snmp_target_mib, snmp_notification_mib, + snmp_view_based_acm_mib]. + +standard_mibs_2(suite) -> + [snmpv2_mib_2, snmp_community_mib_2, + snmp_framework_mib_2, + snmp_target_mib_2, snmp_notification_mib_2, + snmp_view_based_acm_mib_2]. + +standard_mibs_3(suite) -> + [snmpv2_mib_3,snmp_framework_mib_3, snmp_mpd_mib_3, + snmp_target_mib_3, snmp_notification_mib_3, + snmp_view_based_acm_mib_3, snmp_user_based_sm_mib_3]. + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v1. +%% o Test the counters and control objects in SNMP-STANDARD-MIB +%%----------------------------------------------------------------- +snmp_standard_mib(suite) -> []; +snmp_standard_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?DBG("snmp_standard_mib -> std_mib_init", []), + try_test(std_mib_init), + + ?DBG("snmp_standard_mib -> std_mib_a", []), + InBadVsns = try_test(std_mib_a), + put(vsn, v2), + ?DBG("snmp_standard_mib -> std_mib_read", []), + try_test(std_mib_read), + put(vsn, v1), + + ?DBG("snmp_standard_mib -> std_mib_b (~w)", [InBadVsns]), + Bad = try_test(std_mib_b, [InBadVsns]), + ?DBG("snmp_standard_mib -> std_mib_read (community: 'bad community')", []), + try_test(std_mib_read, [], [{community, "bad community"}]), + ?DBG("snmp_standard_mib -> std_mib_write (community: 'public')", []), + try_test(std_mib_write, [], [{community, "public"}]), + ?DBG("snmp_standard_mib -> std_mib_asn_err", []), + try_test(std_mib_asn_err), + ?DBG("snmp_standard_mib -> std_mib_c (~w)", [Bad]), + try_test(std_mib_c, [Bad]), + ?DBG("snmp_standard_mib -> std_mib_a", []), + try_test(standard_mib_a), + + ?DBG("snmp_standard_mib -> std_mib_finish", []), + try_test(std_mib_finish), + ?DBG("snmp_standard_mib -> std_mib_test_finish", []), + try_test(standard_mib_test_finish, [], [{community, "bad community"}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_a() -> + ?line [OutPkts] = get_req(2, [[snmpOutPkts,0]]), + ?line [OutPkts2] = get_req(3, [[snmpOutPkts,0]]), + ?line OutPkts2 = OutPkts + 1, + %% There are some more counters we could test here, but it's not that + %% important, since they are removed from SNMPv2-MIB. + ok. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_init() -> + %% disable authentication failure traps. (otherwise w'd get many of + %% them - this is also a test to see that it works). + s([{[snmpEnableAuthenTraps,0], 2}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 2}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_finish() -> + %% enable again + s([{[snmpEnableAuthenTraps,0], 1}]), + ?line expect(1, [{[snmpEnableAuthenTraps, 0], 1}]). + +%% Req. SNMP-STANDARD-MIB +standard_mib_test_finish() -> + %% force a authenticationFailure + std_mib_write(), + %% check that we got a trap + ?line expect(2, trap, [1,2,3], 4, 0, []). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_read() -> + ?DBG("std_mib_read -> entry", []), + g([[sysUpTime,0]]), % try a bad <something>; msg dropped, no reply + ?DBG("std_mib_read -> await timeout (i.e. no reply)", []), + ?line expect(1, timeout). % make sure we don't get a trap! + + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_write() -> + ?DBG("std_mib_write -> entry", []), + s([{[sysLocation, 0], "new_value"}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_asn_err() -> + snmp_test_mgr:send_bytes([48,99,67,12,0,0,0,0,0,0,5]). + +%%----------------------------------------------------------------- +%% For this test, the agent is configured for v2 and v3. +%% o Test the counters and control objects in SNMPv2-MIB +%%----------------------------------------------------------------- +snmpv2_mib_2(suite) -> []; +snmpv2_mib_2(Config) when list(Config) -> + ?LOG("snmpv2_mib_2 -> start",[]), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?DBG("snmpv2_mib_2 -> standard mib init",[]), + try_test(std_mib_init), + + ?DBG("snmpv2_mib_2 -> get number of (so far) bad versions",[]), + InBadVsns = try_test(std_mib_a), + + ?DBG("snmpv2_mib_2 -> make a bad version read",[]), + put(vsn, v1), + try_test(std_mib_read), + + ?DBG("snmpv2_mib_2 -> bad version read",[]), + put(vsn, v2), + Bad = try_test(std_mib_b, [InBadVsns]), + + ?DBG("snmpv2_mib_2 -> read with bad community",[]), + try_test(std_mib_read, [], [{community, "bad community"}]), + + ?DBG("snmpv2_mib_2 -> write with public community",[]), + try_test(std_mib_write, [], [{community, "public"}]), + + ?DBG("snmpv2_mib_2 -> asn err",[]), + try_test(std_mib_asn_err), + + ?DBG("snmpv2_mib_2 -> check counters",[]), + try_test(std_mib_c, [Bad]), + + ?DBG("snmpv2_mib_2 -> get som counters",[]), + try_test(snmpv2_mib_a), + + ?DBG("snmpv2_mib_2 -> enable auth traps, and await some",[]), + try_test(std_mib_finish), + + ?DBG("snmpv2_mib_2 -> force auth failure, and await trap, " + "then disable auth traps",[]), + try_test(snmpv2_mib_test_finish, [], [{community, "bad community"}]), + + ?LOG("snmpv2_mib_2 -> done",[]). + +%% Req. SNMPv2-MIB +snmpv2_mib_3(suite) -> []; +snmpv2_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + InBadVsns = try_test(std_mib_a), + put(vsn, v1), + try_test(std_mib_read), + put(vsn, v3), + _Bad = try_test(std_mib_b, [InBadVsns]), + try_test(snmpv2_mib_a), + + try_test(std_mib_finish). + +-define(authenticationFailure, [1,3,6,1,6,3,1,1,5,5]). + +%% Req. SNMPv2-MIB +snmpv2_mib_test_finish() -> + %% force a authenticationFailure + ?DBG("ma_v2_inform -> write to std mib",[]), + std_mib_write(), + + %% check that we got a trap + ?DBG("ma_v2_inform -> await trap",[]), + ?line expect(2, v2trap, [{[sysUpTime,0], any}, + {[snmpTrapOID,0], ?authenticationFailure}]), + + %% and the the inform + ?DBG("ma_v2_inform -> await inform",[]), + ?line expect(2, {inform,true}, [{[sysUpTime,0], any}, + {[snmpTrapOID,0],?authenticationFailure}]). + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_a() -> + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + + ?line [InBadVsns] = get_req(4, [[snmpInBadVersions,0]]), + InBadVsns. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_b(InBadVsns) -> + ?line [InBadVsns2] = get_req(1, [[snmpInBadVersions,0]]), + ?line InBadVsns2 = InBadVsns + 1, + ?line [InPkts] = get_req(2, [[snmpInPkts,0]]), + ?line [InPkts2] = get_req(3, [[snmpInPkts,0]]), + ?line InPkts2 = InPkts + 1, + ?line [InBadCommunityNames, InBadCommunityUses, InASNErrs] = + get_req(4, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + {InBadCommunityNames, InBadCommunityUses, InASNErrs}. + +%% Req. SNMP-STANDARD-MIB | SNMPv2-MIB +std_mib_c({InBadCommunityNames, InBadCommunityUses, InASNErrs}) -> + ?line [InBadCommunityNames2, InBadCommunityUses2, InASNErrs2] = + get_req(1, [[snmpInBadCommunityNames,0], + [snmpInBadCommunityUses,0], + [snmpInASNParseErrs, 0]]), + ?line InBadCommunityNames2 = InBadCommunityNames + 1, + ?line InBadCommunityUses2 = InBadCommunityUses + 1, + ?line InASNErrs2 = InASNErrs + 1. + +%% Req. SNMPv2-MIB +snmpv2_mib_a() -> + ?line [SetSerial] = get_req(2, [[snmpSetSerialNo,0]]), + s([{[snmpSetSerialNo,0], SetSerial}, {[sysLocation, 0], "val2"}]), + ?line expect(3, [{[snmpSetSerialNo,0], SetSerial}, + {[sysLocation, 0], "val2"}]), + s([{[sysLocation, 0], "val3"}, {[snmpSetSerialNo,0], SetSerial}]), + ?line expect(4, inconsistentValue, 2, + [{[sysLocation, 0], "val3"}, + {[snmpSetSerialNo,0], SetSerial}]), + ?line ["val2"] = get_req(5, [[sysLocation,0]]). + + +%%----------------------------------------------------------------- +%% o Bad community uses/name is tested already +%% in SNMPv2-MIB and STANDARD-MIB. +%% o Test add/deletion of rows. +%%----------------------------------------------------------------- +snmp_community_mib(suite) -> []; +snmp_community_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + try_test(snmp_community_mib), + ?line unload_master("SNMP-COMMUNITY-MIB"). + +snmp_community_mib_2(X) -> snmp_community_mib(X). + +%% Req. SNMP-COMMUNITY-MIB +snmp_community_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o Test engine boots / time +%%----------------------------------------------------------------- +snmp_framework_mib(suite) -> []; +snmp_framework_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + try_test(snmp_framework_mib), + ?line unload_master("SNMP-FRAMEWORK-MIB"). + +snmp_framework_mib_2(X) -> snmp_framework_mib(X). + +snmp_framework_mib_3(suite) -> []; +snmp_framework_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(snmp_framework_mib). + + +%% Req. SNMP-FRAMEWORK-MIB +snmp_framework_mib() -> + ?line ["agentEngine"] = get_req(1, [[snmpEngineID,0]]), + ?line [EngineTime] = get_req(2, [[snmpEngineTime,0]]), + sleep(5000), + ?line [EngineTime2] = get_req(3, [[snmpEngineTime,0]]), + if + EngineTime+7 < EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + EngineTime+4 > EngineTime2 -> + ?line ?FAIL({too_large_diff, EngineTime, EngineTime2}); + true -> ok + end, + ?line case get_req(4, [[snmpEngineBoots,0]]) of + [Boots] when integer(Boots) -> ok; + Else -> ?FAIL(Else) + end, + ok. + +%%----------------------------------------------------------------- +%% o Test the counters +%%----------------------------------------------------------------- +snmp_mpd_mib_3(suite) -> []; +snmp_mpd_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + UnknownPDUHs = try_test(snmp_mpd_mib_a), + try_test(snmp_mpd_mib_b, [], [{context_engine_id, "bad engine"}]), + try_test(snmp_mpd_mib_c, [UnknownPDUHs]). + + +%% Req. SNMP-MPD-MIB +snmp_mpd_mib_a() -> + ?line [UnknownSecs, InvalidMsgs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0]]), + Pdu = #pdu{type = 'get-request', + request_id = 23, + error_status = noError, + error_index = 0, + varbinds = []}, + SPdu = #scopedPdu{contextEngineID = "agentEngine", + contextName = "", + data = Pdu}, + ?line SPDUBytes = snmp_pdus:enc_scoped_pdu(SPdu), + V3Hdr1 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [7], + msgSecurityModel = 23, % bad sec model + msgSecurityParameters = []}, + V3Hdr2 = #v3_hdr{msgID = 21, + msgMaxSize = 484, + msgFlags = [6], % bad flag combination + msgSecurityModel = 3, + msgSecurityParameters = []}, + Message1 = #message{version = 'version-3', vsn_hdr = V3Hdr1, + data = SPDUBytes}, + Message2 = #message{version = 'version-3', vsn_hdr = V3Hdr2, + data = SPDUBytes}, + ?line MsgBytes1 = snmp_pdus:enc_message_only(Message1), + ?line MsgBytes2 = snmp_pdus:enc_message_only(Message2), + snmp_test_mgr:send_bytes(MsgBytes1), + snmp_test_mgr:send_bytes(MsgBytes2), + + ?line [UnknownSecs2, InvalidMsgs2, UnknownPDUHs] = + get_req(1, [[snmpUnknownSecurityModels,0], + [snmpInvalidMsgs,0], + [snmpUnknownPDUHandlers, 0]]), + ?line UnknownSecs2 = UnknownSecs + 1, + ?line InvalidMsgs2 = InvalidMsgs + 1, + UnknownPDUHs. + +-define(snmpUnknownPDUHandlers_instance, [1,3,6,1,6,3,11,2,1,3,0]). +snmp_mpd_mib_b() -> + g([[sysUpTime,0]]), + ?line expect(1, report, [{?snmpUnknownPDUHandlers_instance, any}]). + + +snmp_mpd_mib_c(UnknownPDUHs) -> + ?line [UnknownPDUHs2] = get_req(1, [[snmpUnknownPDUHandlers, 0]]), + ?line UnknownPDUHs2 = UnknownPDUHs + 1. + + +snmp_target_mib(suite) -> []; +snmp_target_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-TARGET-MIB"), + try_test(snmp_target_mib), + ?line unload_master("SNMP-TARGET-MIB"). + +snmp_target_mib_2(X) -> snmp_target_mib(X). + +snmp_target_mib_3(X) -> snmp_target_mib(X). + +snmp_target_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +snmp_notification_mib(suite) -> []; +snmp_notification_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + try_test(snmp_notification_mib), + ?line unload_master("SNMP-NOTIFICATION-MIB"). + +snmp_notification_mib_2(X) -> snmp_notification_mib(X). + +snmp_notification_mib_3(X) -> snmp_notification_mib(X). + +snmp_notification_mib() -> + ?INF("NOT YET IMPLEMENTED", []), + nyi. + +%%----------------------------------------------------------------- +%% o add/delete views and try them +%% o try boundaries +%%----------------------------------------------------------------- +snmp_view_based_acm_mib(suite) -> []; +snmp_view_based_acm_mib(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master("Test2"), + snmp_view_based_acm_mib(), + ?line unload_master("Test2"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +snmp_view_based_acm_mib_2(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib_3(X) -> snmp_view_based_acm_mib(X). + +snmp_view_based_acm_mib() -> + snmpa:verbosity(net_if,trace), + snmpa:verbosity(master_agent,trace), + ?LOG("start snmp_view_based_acm_mib test",[]), + %% The user "no-rights" is present in USM, and is mapped to security + %% name 'no-rights", which is not present in VACM. + %% So, we'll add rights for it, try them and delete them. + %% We'll give "no-rights" write access to tDescr.0 and read access + %% to tDescr2.0 + %% These are the options we'll use to the mgr + Opts = [{user, "no-rights"}, {community, "no-rights"}], + %% Find the valid secmodel, and one invalid secmodel. + {SecMod, InvSecMod} = + case get(vsn) of + v1 -> {?SEC_V1, ?SEC_V2C}; + v2 -> {?SEC_V2C, ?SEC_USM}; + v3 -> {?SEC_USM, ?SEC_V1} + end, + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Now, add a mapping from "no-rights" -> "no-rights-group" + GRow1Status = [vacmSecurityToGroupStatus,[SecMod, 9,"no-rights"]], + GRow1 = + [{[vacmGroupName, [SecMod, 9,"no-rights"]], "no-rights-group"}, + {GRow1Status, ?createAndGo}], + ?DBG("set '~p'",[GRow1]), + ?line try_test(do_set, [GRow1]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Create a mapping for another sec model, and make sure it dosn't + %% give us access + GRow2Status = [vacmSecurityToGroupStatus,[InvSecMod, 9,"no-rights"]], + GRow2 = [{[vacmGroupName, [InvSecMod, 9, "no-rights"]], "initial"}, + {GRow2Status, ?createAndGo}], + + ?DBG("set '~p'",[GRow2]), + ?line try_test(do_set, [GRow2]), + + ?DBG("assign rights for 'no-rights'",[]), + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [GRow2Status]), + + RVName = "rv_name", + WVName = "wv_name", + + %% Access row + ARow1Idx = [15 | "no-rights-group"] ++ [0, ?SEC_ANY, 1], + ARow1Status = [vacmAccessStatus, ARow1Idx], + ARow1 = [{[vacmAccessContextMatch, ARow1Idx], 1}, + {[vacmAccessReadViewName, ARow1Idx], RVName}, + {[vacmAccessWriteViewName, ARow1Idx], WVName}, + {ARow1Status, ?createAndGo}], + + %% This access row would give acces, if InvSecMod was valid. + ARow2Idx = [15 | "no-rights-group"] ++ [0, InvSecMod, 1], + ARow2Status = [vacmAccessStatus, ARow2Idx], + ARow2 = [{[vacmAccessContextMatch, ARow2Idx], 1}, + {[vacmAccessReadViewName, ARow2Idx], "internet"}, + {[vacmAccessWriteViewName, ARow2Idx], "internet"}, + {ARow2Status, ?createAndGo}], + + ?line try_test(do_set, [ARow2]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete that row + ?line try_test(del_row, [ARow2Status]), + + + %% Add valid row + ?line try_test(do_set, [ARow1]), + + ?line try_test(use_no_rights, [], Opts), + + %% Create the view family + VRow1Idx = mk_ln(RVName) ++ mk_ln(?xDescr), % object access + VRow2Idx = mk_ln(RVName) ++ mk_ln(?xDescr2 ++ [0]), % instance access + VRow3Idx = mk_ln(WVName) ++ mk_ln(?xDescr), % object access + VRow4Idx = mk_ln(WVName) ++ mk_ln(?xDescr ++ [0]), % instance access + VRow1Status = [vacmViewTreeFamilyStatus, VRow1Idx], + VRow2Status = [vacmViewTreeFamilyStatus, VRow2Idx], + VRow3Status = [vacmViewTreeFamilyStatus, VRow3Idx], + VRow4Status = [vacmViewTreeFamilyStatus, VRow4Idx], + + ?line try_test(add_row, [VRow1Status]), + ?line try_test(add_row, [VRow2Status]), + ?line try_test(add_row, [VRow3Status]), + + %% We're supposed to have access now... + ?line try_test(use_rights, [], Opts), + + %% Change Row3 to Row4 + ?line try_test(del_row, [VRow3Status]), + ?line try_test(add_row, [VRow4Status]), + + %% We should still have access... + ?line try_test(use_rights, [], Opts), + + %% Delete rows + ?line try_test(del_row, [GRow1Status]), + + ?line try_test(use_no_rights, [], Opts), + + %% Delete rest of rows + ?line try_test(del_row, [ARow1Status]), + ?line try_test(del_row, [VRow1Status]), + ?line try_test(del_row, [VRow2Status]), + ?line try_test(del_row, [VRow4Status]), + + ?line try_test(use_no_rights, [], Opts), + snmpa:verbosity(master_agent,log). + +do_set(Row) -> + s(Row), + expect(1, Row). + +add_row(RowStatus) -> + s([{RowStatus, ?createAndGo}]), + expect(1, [{RowStatus, ?createAndGo}]). + +del_row(RowStatus) -> + s([{RowStatus, ?destroy}]), + expect(1, [{RowStatus, ?destroy}]). + + + +use_no_rights() -> + g([[xDescr,0]]), + ?v1_2_3(expect(11, noSuchName, 1, any), + expect(12, [{[xDescr,0], noSuchObject}]), + expect(13, authorizationError, 1, any)), + g([[xDescr2,0]]), + ?v1_2_3(expect(21, noSuchName, 1, any), + expect(22, [{[xDescr2,0], noSuchObject}]), + expect(23, authorizationError, 1, any)), + gn([[xDescr]]), + ?v1_2_3(expect(31, noSuchName, 1, any), + expect(32, [{[xDescr], endOfMibView}]), + expect(33, authorizationError, 1, any)), + s([{[xDescr,0], "tryit"}]), + ?v1_2_3(expect(41, noSuchName, 1, any), + expect(42, noAccess, 1, any), + expect(43, authorizationError, 1, any)). + + +use_rights() -> + g([[xDescr,0]]), + expect(1, [{[xDescr,0], any}]), + g([[xDescr2,0]]), + expect(2, [{[xDescr2,0], any}]), + s([{[xDescr,0], "tryit"}]), + expect(3, noError, 0, any), + g([[xDescr,0]]), + expect(4, [{[xDescr,0], "tryit"}]). + +mk_ln(X) -> + [length(X) | X]. + +%%----------------------------------------------------------------- +%% o add/delete users and try them +%% o test all secLevels +%% o test all combinations of protocols +%% o try bad ops; check counters +%%----------------------------------------------------------------- +snmp_user_based_sm_mib_3(suite) -> []; +snmp_user_based_sm_mib_3(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + _AgentDir = ?config(agent_dir, Config), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + + %% The newUser used here already has VACM access. + + %% Add a new user in the simplest way; just createAndGo + try_test(v3_sync, [[{usm_add_user1, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new user + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey1 = snmp:passwd2localized_key(sha, "new sha password", "agentEngine"), + DesKey1 = lists:sublist(ShaKey1, 16), + + %% Change the new user's keys - 1 + try_test(v3_sync, [[{usm_key_change1, [ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + MgrDir = ?config(mgr_dir, Config), + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + + ShaKey2 = snmp:passwd2localized_key(sha, "newer password", "agentEngine"), + DesKey2 = lists:sublist(ShaKey2, 16), + + %% Change the new user's keys - 2 + ?line try_test(v3_sync, + [[{usm_key_change2, [ShaKey1, DesKey1, ShaKey2, DesKey2]}]], + [{sec_level, authPriv}, {user, "newUser"}]), + + %% Try to use the new keys + reset_usm_mgr(MgrDir), + ?line rewrite_usm_mgr(MgrDir, ShaKey2, DesKey2), + ?line load_master("Test2"), + ?line try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Change the new user's keys - 3 + ?line try_test(v3_sync, + [[{usm_key_change3, [ShaKey2, DesKey2, ShaKey1, DesKey1]}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try to use the new keys + ?line rewrite_usm_mgr(MgrDir, ShaKey1, DesKey1), + ?line load_master("Test2"), + try_test(v3_sync, [[{usm_use_user, []}]], + [{sec_level, authPriv}, {user, "newUser"}]), + ?line unload_master("Test2"), + reset_usm_mgr(MgrDir), + + %% Try some read requests + ?line try_test(v3_sync, [[{usm_read, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Delete the new user + ?line try_test(v3_sync, [[{usm_del_user, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + %% Try some bad requests + ?line try_test(v3_sync, [[{usm_bad, []}]], + [{sec_level, authPriv}, {user, "privDES"}]), + + ?line unload_master("SNMP-USER-BASED-SM-MIB"). + +-define(usmUserSecurityName, [1,3,6,1,6,3,15,1,2,2,1,3]). + +usm_add_user1() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +usm_use_user() -> + v2_proc(). + + +%% Change own public keys +usm_key_change1(ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_shaxxxxxxxxxx", + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + "passwd_desxxxxxx", + DesKey), + Vbs1 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change own private keys +usm_key_change2(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs1), + ?line expect(1, Vbs1). + +%% Change other's public keys +usm_key_change3(OldShaKey, OldDesKey, ShaKey, DesKey) -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ShaKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldShaKey, + ShaKey), + DesKeyChange = snmp_user_based_sm_mib:mk_key_change(sha, + OldDesKey, + DesKey), + Vbs1 = [{[usmUserOwnAuthKeyChange, NewRowIndex], ShaKeyChange}], + s(Vbs1), + ?line expect(1, noAccess, 1, any), + Vbs2 = [{[usmUserOwnPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs2), + ?line expect(2, noAccess, 1, any), + + + Vbs3 = [{[usmUserAuthKeyChange, NewRowIndex], ShaKeyChange}, + {[usmUserPrivKeyChange, NewRowIndex], DesKeyChange}], + s(Vbs3), + ?line expect(1, Vbs3). + +usm_read() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + ?line g([[usmUserSecurityName, NewRowIndex], + [usmUserCloneFrom, NewRowIndex], + [usmUserAuthKeyChange, NewRowIndex], + [usmUserOwnAuthKeyChange, NewRowIndex], + [usmUserPrivKeyChange, NewRowIndex], + [usmUserOwnPrivKeyChange, NewRowIndex]]), + ?line expect(1, + [{[usmUserSecurityName, NewRowIndex], "newUser"}, + {[usmUserCloneFrom, NewRowIndex], [0,0]}, + {[usmUserAuthKeyChange, NewRowIndex], ""}, + {[usmUserOwnAuthKeyChange, NewRowIndex], ""}, + {[usmUserPrivKeyChange, NewRowIndex], ""}, + {[usmUserOwnPrivKeyChange, NewRowIndex], ""}]), + ok. + + + +usm_del_user() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + Vbs1 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs1), + ?line expect(1, Vbs1), + ok. + +-define(usmUserCloneFrom, [1,3,6,1,6,3,15,1,2,2,1,4]). + +-define(usmNoAuthProtocol, [1,3,6,1,6,3,10,1,1,1]). + +-define(usmHMACMD5AuthProtocol, [1,3,6,1,6,3,10,1,1,2]). + +-define(usmHMACSHAAuthProtocol, [1,3,6,1,6,3,10,1,1,3]). + +-define(usmNoPrivProtocol, [1,3,6,1,6,3,10,1,2,1]). + +-define(usmDESPrivProtocol, [1,3,6,1,6,3,10,1,2,2]). + +usm_bad() -> + NewRowIndex = [11,"agentEngine", 7, "newUser"], + RowPointer1 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDOS"], + Vbs1 = [{[usmUserCloneFrom, NewRowIndex], RowPointer1}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs1), + ?line expect(1, inconsistentName, 1, any), + + RowPointer2 = ?usmUserCloneFrom ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs2 = [{[usmUserCloneFrom, NewRowIndex], RowPointer2}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs2), + ?line expect(2, wrongValue, 1, any), + + RowPointer3 = ?usmUserSecurityName ++ [11|"agentEngine"] ++ [7|"privDES"], + Vbs3 = [{[usmUserCloneFrom, NewRowIndex], RowPointer3}, + {[usmUserStatus, NewRowIndex], ?createAndGo}], + ?line s(Vbs3), + ?line expect(3, Vbs3), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmNoAuthProtocol}]), + ?line expect(4, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmHMACMD5AuthProtocol}]), + ?line expect(5, inconsistentValue, 1, any), + ?line s([{[usmUserAuthProtocol, NewRowIndex], ?usmDESPrivProtocol}]), + ?line expect(6, wrongValue, 1, any), + ?line s([{[usmUserPrivProtocol, NewRowIndex], ?usmHMACSHAAuthProtocol}]), + ?line expect(7, wrongValue, 1, any), + + Vbs4 = [{[usmUserStatus, NewRowIndex], ?destroy}], + ?line s(Vbs4), + ?line expect(1, Vbs4), + + ok. + + +%%----------------------------------------------------------------- +%% Loop through entire MIB, to make sure that all instrum. funcs +%% works. +%% Load all std mibs that are not loaded by default. +%%----------------------------------------------------------------- +loop_mib(suite) -> []; +loop_mib(Config) when list(Config) -> + ?LOG("loop_mib -> initiate case",[]), + %% snmpa:verbosity(master_agent,debug), + %% snmpa:verbosity(mib_server,info), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib -> load mib SNMP-COMMUNITY-MIB",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> load mib SNMP-MPD-MIB",[]), + ?line load_master_std("SNMP-MPD-MIB"), + ?DBG("loop_mib -> load mib SNMP-TARGET-MIB",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> load mib SNMP-NOTIFICATION-MIB",[]), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> load mib SNMP-FRAMEWORK-MIB",[]), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> load mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?DBG("loop_mib -> try",[]), + try_test(loop_mib_1), + ?DBG("loop_mib -> unload mib SNMP-COMMUNITY-MIB",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?DBG("loop_mib -> unload mib SNMP-MPD-MIB",[]), + ?line unload_master("SNMP-MPD-MIB"), + ?DBG("loop_mib -> unload mib SNMP-TARGET-MIB",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?DBG("loop_mib -> unload mib SNMP-NOTIFICATION-MIB",[]), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?DBG("loop_mib -> unload mib SNMP-FRAMEWORK-MIB",[]), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?DBG("loop_mib -> unload mib SNMP-VIEW-BASED-ACM-MIB",[]), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + %% snmpa:verbosity(master_agent,log), + %% snmpa:verbosity(mib_server,silence), + ?LOG("loop_mib -> done",[]). + + +loop_mib_2(suite) -> []; +loop_mib_2(Config) when list(Config) -> + ?LOG("loop_mib_2 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_2 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_2 -> load mibs",[]), + ?line load_master_std("SNMP-COMMUNITY-MIB"), + ?line load_master_std("SNMP-MPD-MIB"), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-FRAMEWORK-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_2 -> unload mibs",[]), + ?line unload_master("SNMP-COMMUNITY-MIB"), + ?line unload_master("SNMP-MPD-MIB"), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-FRAMEWORK-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?LOG("loop_mib_2 -> done",[]). + + +loop_mib_3(suite) -> []; +loop_mib_3(Config) when list(Config) -> + ?LOG("loop_mib_3 -> initiate case",[]), + {SaNode, MgrNode, MibDir} = init_case(Config), + ?DBG("loop_mib_3 -> ~n" + "\tSaNode: ~p~n" + "\tMgrNode: ~p~n" + "\tMibDir: ~p",[SaNode, MgrNode, MibDir]), + ?DBG("loop_mib_3 -> load mibs",[]), + ?line load_master_std("SNMP-TARGET-MIB"), + ?line load_master_std("SNMP-NOTIFICATION-MIB"), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + ?line load_master_std("SNMP-USER-BASED-SM-MIB"), + try_test(loop_mib_2), + ?DBG("loop_mib_3 -> unload mibs",[]), + ?line unload_master("SNMP-TARGET-MIB"), + ?line unload_master("SNMP-NOTIFICATION-MIB"), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"), + ?line unload_master("SNMP-USER-BASED-SM-MIB"), + ?LOG("loop_mib_3 -> done",[]). + + +%% Req. As many mibs all possible +loop_mib_1() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_1([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_1(Oid, N) -> + ?DBG("loop_it_1 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_1 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_1 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_1(NOid, N+1); + #pdu{type='get-response', error_status=noSuchName, error_index=1, + varbinds=[_]} -> + ?DBG("loop_it_1 -> done",[]), + N; + + #pdu{type = Type, error_status = Err, error_index = Idx, + varbinds = Vbs} -> + exit({unexpected_pdu, ?LINE, Type, Err, Idx, Vbs}) + end. + +%% Req. As many mibs all possible +loop_mib_2() -> + ?DBG("loop_mib_1 -> entry",[]), + N = loop_it_2([1,1], 0), + io:format(user, "found ~w varibles\n", [N]), + ?line N = if N < 100 -> 100; + true -> N + end. + + +loop_it_2(Oid, N) -> + ?DBG("loop_it_2 -> entry with~n" + "\tOid: ~p~n" + "\tN: ~p",[Oid,N]), + case get_next_req([Oid]) of + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid, value = endOfMibView}]} -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p",[NOid]), + N; + #pdu{type='get-response', error_status=noError, error_index=0, + varbinds=[#varbind{oid = NOid,value = Value}]} when NOid > Oid -> + ?DBG("loop_it_2 -> ~n" + "\tNOid: ~p~n" + "\tValue: ~p",[NOid,Value]), + ?line [Value2] = get_req(1, [NOid]), % must not be same + ?DBG("loop_it_2 -> ~n" + "\tValue2: ~p",[Value2]), + loop_it_2(NOid, N+1) + end. + + +%%%----------------------------------------------------------------- +%%% Testing of reported bugs and other tickets. +%%%----------------------------------------------------------------- + +reported_bugs(suite) -> + [otp_1128, otp_1129, otp_1131, otp_1162, + otp_1222, otp_1298, otp_1331, otp_1338, + otp_1342, otp_2776, otp_2979, otp_3187, otp_3725]. + +reported_bugs_2(suite) -> + [otp_1128_2, otp_1129_2, otp_1131_2, otp_1162_2, + otp_1222_2, otp_1298_2, otp_1331_2, otp_1338_2, + otp_1342_2, otp_2776_2, otp_2979_2, otp_3187_2]. + +reported_bugs_3(suite) -> + [otp_1128_3, otp_1129_3, otp_1131_3, otp_1162_3, + otp_1222_3, otp_1298_3, otp_1331_3, otp_1338_3, + otp_1342_3, otp_2776_3, otp_2979_3, otp_3187_3, + otp_3542]. + + +%% These are (ticket) test cases where the initiation has to be done +%% individually. +tickets(suite) -> + [otp_4394]. + +%%----------------------------------------------------------------- +%% Ticket: OTP-1128 +%% Slogan: Bug in handling of createAndWait set-requests. +%%----------------------------------------------------------------- +otp_1128(suite) -> []; +otp_1128(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1128), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1128_2(X) -> otp_1128(X). + +otp_1128_3(X) -> otp_1128(X). + +otp_1128() -> + io:format("Testing bug reported in ticket OTP-1128...~n"), + + NewKeyc3 = [intCommunityViewIndex,get(mip),is("test")], + NewKeyc4 = [intCommunityAccess,get(mip),is("test")], + NewKeyc5 = [intCommunityStatus,get(mip),is("test")], + + s([{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + ?line expect(28, [{NewKeyc5, ?createAndWait}, {NewKeyc4, 2}]), + g([NewKeyc5]), + ?line expect(29, [{NewKeyc5, ?notReady}]), + s([{NewKeyc5, ?active}, {NewKeyc3, 2}]), + ?line expect(30, [{NewKeyc5, ?active}, {NewKeyc3, 2}]), + g([NewKeyc5]), + ?line expect(31, [{NewKeyc5, ?active}]), + s([{NewKeyc5, ?destroy}]), + ?line expect(32, [{NewKeyc5, ?destroy}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1129, OTP-1169 +%% Slogan: snmpa:int_to_enum crashes on bad oids +%%----------------------------------------------------------------- +otp_1129(suite) -> []; +otp_1129(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + try_test(otp_1129_i, [node()]), + ?line unload_master("Klas3"). + +otp_1129_2(X) -> otp_1129(X). + +otp_1129_3(X) -> otp_1129(X). + +otp_1129_i(MaNode) -> + io:format("Testing bug reported in ticket OTP-1129...~n"), + false = rpc:call(MaNode, snmp, int_to_enum, [iso, 1]), + false = rpc:call(MaNode, snmp, int_to_enum, [isox, 1]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1131 +%% Slogan: Agent crashes / erlang node halts if RowIndex in a +%% setrequest is of bad type, e.g. an INDEX {INTEGER}, +%% and RowIdenx [3,2]. +%%----------------------------------------------------------------- +otp_1131(suite) -> []; +otp_1131(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas1"), + try_test(otp_1131), + ?line unload_master("Klas1"). + +otp_1131_2(X) -> otp_1131(X). + +otp_1131_3(X) -> otp_1131(X). + +otp_1131() -> + io:format("Testing bug reported in ticket OTP-1131...~n"), + s([{[friendsEntry, [2, 3, 1]], s, "kompis3"}, + {[friendsEntry, [3, 3, 1]], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 2, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1162 +%% Slogan: snmp_agent can't handle wrongValue from instrum.func +%%----------------------------------------------------------------- +otp_1162(suite) -> []; +otp_1162(Config) when list(Config) -> + {SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line {ok, SA} = start_subagent(SaNode, ?sa, "SA-MIB"), + try_test(otp_1162), + stop_subagent(SA). + +otp_1162_2(X) -> otp_1162(X). + +otp_1162_3(X) -> otp_1162(X). + +otp_1162() -> + s([{[sa, [2,0]], 6}]), % wrongValue (i is_set_ok) + ?line expect(1, ?v1_2(badValue, wrongValue), 1, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1222 +%% Slogan: snmp agent crash if faulty index is returned from instrum +%%----------------------------------------------------------------- +otp_1222(suite) -> []; +otp_1222(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas3"), + ?line load_master("Klas4"), + try_test(otp_1222), + ?line unload_master("Klas3"), + ?line unload_master("Klas4"). + +otp_1222_2(X) -> otp_1222(X). + +otp_1222_3(X) -> otp_1222(X). + +otp_1222() -> + io:format("Testing bug reported in ticket OTP-1222...~n"), + s([{[fStatus4,1], 4}, {[fName4,1], 1}]), + ?line expect(1, genErr, 0, any), + s([{[fStatus4,2], 4}, {[fName4,2], 1}]), + ?line expect(2, genErr, 0, any). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1298 +%% Slogan: Negative INTEGER values are treated as positive. +%%----------------------------------------------------------------- +otp_1298(suite) -> []; +otp_1298(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1298), + ?line unload_master("Klas2"). + +otp_1298_2(X) -> otp_1298(X). + +otp_1298_3(X) -> otp_1298(X). + +otp_1298() -> + io:format("Testing bug reported in ticket OTP-1298...~n"), + s([{[fint,0], -1}]), + ?line expect(1298, [{[fint,0], -1}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1331 +%% Slogan: snmp_generic should return noError when deleting non-ex row +%%----------------------------------------------------------------- +otp_1331(suite) -> []; +otp_1331(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1331), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1331_2(X) -> otp_1331(X). + +otp_1331_3(X) -> otp_1331(X). + +otp_1331() -> + NewKeyc5 = [intCommunityStatus,[127,32,0,0],is("test")], + s([{NewKeyc5, ?destroy}]), + ?line expect(1, [{NewKeyc5, ?destroy}]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1338 +%% Slogan: snmp bug in initialisation of default values for mnesia tabs +%%----------------------------------------------------------------- +otp_1338(suite) -> []; +otp_1338(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas2"), + try_test(otp_1338), + ?line unload_master("Klas2"). + +otp_1338_2(X) -> otp_1338(X). + +otp_1338_3(X) -> otp_1338(X). + +otp_1338() -> + s([{[kStatus2, 7], i, ?createAndGo}]), + ?line expect(1, [{[kStatus2, 7], ?createAndGo}]), + g([[kName2, 7]]), + ?line expect(2, [{[kName2, 7], "JJJ"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-1342 +%% Slogan: default impl of snmp table can't handle bad index access, +%% Set when INDEX is read-write gets into an infinite loop! +%%----------------------------------------------------------------- +otp_1342(suite) -> []; +otp_1342(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Klas4"), + try_test(otp_1342), + ?line unload_master("Klas4"). + +otp_1342_2(X) -> otp_1342(X). + +otp_1342_3(X) -> otp_1342(X). + +otp_1342() -> + s([{[fIndex5, 1], i, 1}, + {[fName5, 1], i, 3}, + {[fStatus5, 1], i, ?createAndGo}]), + ?line expect(1, ?v1_2(noSuchName, noCreation), 3, any). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-1366 +%% Slogan: snmp traps not sent to all managers +%% Note: NYI! We need a way to tell the test server that we need +%% mgrs on two different machines. +%%----------------------------------------------------------------- +otp_1366(suite) -> []; +otp_1366(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_1366), + ?line unload_master("OLD-SNMPEA-MIB"). + +otp_1366_2(X) -> otp_1366(X). + +otp_1366_3(X) -> otp_1366(X). + +otp_1366() -> + ?INF("NOT YET IMPLEMENTED", []), + 'NYI'. + +%%----------------------------------------------------------------- +%% Ticket: OTP-2776 +%% Slogan: snmp:validate_date_and_time() fails when time is 00:00 +%%----------------------------------------------------------------- +otp_2776(suite) -> []; +otp_2776(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_2776). + +otp_2776_2(X) -> otp_2776(X). + +otp_2776_3(X) -> otp_2776(X). + +otp_2776() -> + io:format("Testing bug reported in ticket OTP-2776...~n"), + + Dt01_valid = [19,98,9,1,1,0,23,0,43,0,0], + Dt02_valid = [19,98,9,1,0,0,0,0,43,0,0], % This is what is fixed: 00:00 + Dt03_valid = [19,98,2,28,1,0,23,0,43,0,0], + Dt04_invalid = [19,98,2,29,1,0,23,0,43,0,0], + Dt05_valid = [19,96,2,29,1,0,23,0,43,0,0], + Dt06_valid = [20,0,2,29,1,0,23,0,43,0,0], + Dt07_invalid = [19,96,2,30,1,0,23,0,43,0,0], % This is also fixed: 30/2 + Dt08_valid = [19,98,4,30,1,0,23,0,43,0,0], + Dt09_invalid = [19,98,4,31,1,0,23,0,43,0,0], % This is also fixed: 31/4 + Dt10_invalid = [], + Dt11_invalid = [kalle,hobbe], + L = [{ 1, true, Dt01_valid}, + { 2, true, Dt02_valid}, + { 3, true, Dt03_valid}, + { 4, false, Dt04_invalid}, + { 5, true, Dt05_valid}, + { 6, true, Dt06_valid}, + { 7, false, Dt07_invalid}, + { 8, true, Dt08_valid}, + { 9, false, Dt09_invalid}, + {10, false, Dt10_invalid}, + {11, false, Dt11_invalid}], + + ?line ok = validate_dat(L). + + +validate_dat(L) -> validate_dat(L,[]). + +validate_dat([],V) -> + Fun = fun({_,X}) -> case X of + ok -> false; + _ -> true + end + end, + validate_dat1( lists:reverse( lists:filter(Fun,V) ) ); +validate_dat([{Id,E,Dat}|T],V) -> + validate_dat(T,[validate_dat2(Id,E,Dat) | V]). + +validate_dat1([]) -> ok; +validate_dat1(L) -> {error,L}. + +validate_dat2(Id, E, Dat) -> + Res = case {E,snmp:validate_date_and_time(Dat)} of + {E,E} -> ok; + {E,A} -> {E,A} + end, + {Id, Res}. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-2979 +%% Slogan: get-next on more than 1 column in an empty table +%% returns bad response. +%%----------------------------------------------------------------- +otp_2979(suite) -> []; +otp_2979(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master("Test1"), + ?line init_old(), + try_test(otp_2979), + ?line unload_master("Test1"). + +otp_2979_2(X) -> otp_2979(X). + +otp_2979_3(X) -> otp_2979(X). + +otp_2979() -> + gn([[sparseDescr], [sparseStatus]]), + ?line expect(1, [{[sparseStr,0], "slut"}, + {[sparseStr,0], "slut"}]). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3187 +%% Slogan: get-next on vacmAccessTable for colums > 5 returns +%% endOfTable - should return value. +%%----------------------------------------------------------------- +otp_3187(suite) -> []; +otp_3187(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + ?line load_master_std("SNMP-VIEW-BASED-ACM-MIB"), + otp_3187(), + ?line unload_master("SNMP-VIEW-BASED-ACM-MIB"). + +otp_3187_2(X) -> otp_3187(X). + +otp_3187_3(X) -> otp_3187(X). + +otp_3187() -> + ?line Elements = + snmp_view_based_acm_mib:vacmAccessTable(get_next,[],[4,5,6]), + lists:foreach(fun(E) -> + ?line if E == endOfTable -> + ?FAIL(endOfTable); + true -> ok + end + end, Elements). + +%%----------------------------------------------------------------- +%% Ticket: OTP-3542 +%% Slogan: +%%----------------------------------------------------------------- +otp_3542(suite) -> []; +otp_3542(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_3542). + +otp_3542() -> + io:format("SNMP v3 discovery...~n"), + ?line Res = snmp_test_mgr:d(), + io:format("SNMP v3 discovery result: ~p~n",[Res]). + + +%%----------------------------------------------------------------- +%% Ticket: OTP-3725 +%% Slogan: Slow response time on snmpa:int_to_enum +%%----------------------------------------------------------------- +otp_3725(suite) -> []; +otp_3725(Config) when list(Config) -> + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + + ?line load_master("OLD-SNMPEA-MIB"), + ?line init_old(), + try_test(otp_3725_test, [node()]), + ?line unload_master("OLD-SNMPEA-MIB"). + +%% Req. OLD-SNMPEA-MIB +otp_3725_test(MaNode) -> + io:format("Testing feature requested in ticket OTP-3725...~n"), + ?line rpc:call(MaNode,snmpa,verbosity,[symbolic_store,trace]), + ?line Db = rpc:call(MaNode,snmp,get_symbolic_store_db,[]), + ?DBG("otp_3725_test -> Db = ~p",[Db]), + + ?line {value, OID} = rpc:call(MaNode, snmp, name_to_oid, + [Db, intAgentIpAddress]), + ?DBG("otp_3725_test -> name_to_oid for ~p: ~p",[intAgentIpAddress,OID]), + ?line {value, intAgentIpAddress} = rpc:call(MaNode, snmp, oid_to_name, + [Db,OID]), + ?DBG("otp_3725_test -> oid_to_name for ~p: ~p",[OID,intAgentIpAddress]), + ?line false = rpc:call(MaNode, snmp, name_to_oid, [Db, intAgentIpAddres]), + ?line false = rpc:call(MaNode, snmp, oid_to_name, + [Db, [1,5,32,3,54,3,3,34,4]]), + ?line {value, 2} = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, excluded]), + ?line {value, excluded} = rpc:call(MaNode, snmp, int_to_enum, + [Db, intViewType, 2]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intViewType, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddress, exclude]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, intAgentIpAddre, exclude]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, intViewType, 3]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddress, 2]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, + [Db, intAgentIpAddre, 2]), + ?line {value, active} = rpc:call(MaNode, snmp, int_to_enum, + [Db, 'RowStatus', ?active]), + ?line {value, ?destroy} = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'RowStatus', xxxdestroy]), + ?line false = rpc:call(MaNode, snmp, enum_to_int, + [Db, 'xxRowStatus', destroy]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'RowStatus', 25]), + ?line false = rpc:call(MaNode, snmp, int_to_enum, [Db, 'xxRowStatus', 1]), + ok. + + +%%----------------------------------------------------------------- +%% Ticket: OTP-4394 +%% Slogan: Target mib tag list check invalid +%%----------------------------------------------------------------- + + +otp_4394(suite) -> {req, [], {conf, + init_otp_4394, + [otp_4394_test], + finish_otp_4394}}. + +init_otp_4394(Config) when list(Config) -> + ?DBG("init_otp_4394 -> entry with" + "~n Config: ~p", [Config]), + ?line AgentDir = ?config(agent_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line otp_4394_config(AgentDir, MgrDir, Ip), + MasterAgentVerbosity = {master_agent_verbosity, trace}, + NetIfVerbosity = {net_if_verbosity, trace}, + Opts = [MasterAgentVerbosity,NetIfVerbosity], + [{vsn, v1} | start_v1_agent(Config,Opts)]. + +otp_4394_config(AgentDir, MgrDir, Ip0) -> + ?DBG("otp_4394_config -> entry with" + "~n AgentDir: ~p" + "~n MgrDir: ~p" + "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]), + Vsn = [v1], + Ip = tuple_to_list(Ip0), + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip, + ?TRAP_UDP, Ip, 4000, + "OTP-4394 test"), + ?line case update_usm(Vsn, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsn, MgrDir); + false -> + ?line ok + end, + C1 = {"a", "all-rights", "initial", "", "pc"}, + C2 = {"c", "secret", "secret_name", "", "secret_tag"}, + ?line write_community_conf(AgentDir, [C1, C2]), + ?line update_vacm(Vsn, AgentDir), + Ta1 = {"shelob v1", + [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda + "pc1", + "target_v1", "", + %% [255,255,255,255,0,0], + [], + 2048}, + Ta2 = {"bifur v1", + [134,138,177,75], 5000, 1500, 3, %% Anv�nd Ip + "pc2", + "target_v1", "", + %% [255,255,255,255,0,0], + [], 2048}, + ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]), + ?line write_target_params_conf(AgentDir, Vsn), + ?line write_notify_conf(AgentDir), + ok. + + + +finish_otp_4394(Config) when list(Config) -> + ?DBG("finish_otp_4394 -> entry", []), + C1 = stop_agent(Config), + delete_files(C1), + erase(mgr_node), + lists:keydelete(vsn, 1, C1). + +otp_4394_test(suite) -> []; +otp_4394_test(Config) -> + ?DBG("otp_4394_test -> entry", []), + {_SaNode, _MgrNode, _MibDir} = init_case(Config), + try_test(otp_4394_test1), + ?DBG("otp_4394_test -> done", []), + ok. + +otp_4394_test1() -> + ?DBG("otp_4394_test1 -> entry", []), + gn([[1,1]]), + Res = + case snmp_test_mgr:expect(1, [{[sysDescr,0], "Erlang SNMP agent"}]) of + %% {error, 1, {"?",[]}, {"~w",[timeout]}} + {error, 1, _, {_, [timeout]}} -> + ?DBG("otp_4394_test1 -> expected result: timeout", []), + ok; + Else -> + Else + end, + ?DBG("otp_4394_test1 -> done with: ~p", [Res]), + Res. + + +%%%-------------------------------------------------- +%%% Used to test the standard mib with our +%%% configuration. +%%%-------------------------------------------------- +run(F, A, Opts) -> + M = get(mib_dir), + Dir = get(mgr_dir), + User = snmp_misc:get_option(user, Opts, "all-rights"), + SecLevel = snmp_misc:get_option(sec_level, Opts, noAuthNoPriv), + EngineID = snmp_misc:get_option(engine_id, Opts, "agentEngine"), + CtxEngineID = snmp_misc:get_option(context_engine_id, Opts, EngineID), + Community = snmp_misc:get_option(community, Opts, "all-rights"), + ?DBG("run -> start crypto app",[]), + Crypto = case os:type() of + vxworks -> + no_crypto; + _ -> + ?CRYPTO_START() + end, + ?DBG("run -> Crypto: ~p",[Crypto]), + catch snmp_test_mgr:stop(), % If we had a running mgr from a failed case + StdM = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + ?DBG("run -> config:~n" + "\tM: ~p~n" + "\tDir: ~p~n" + "\tUser: ~p~n" + "\tSecLevel: ~p~n" + "\tEngineID: ~p~n" + "\tCtxEngineID: ~p~n" + "\tCommunity: ~p~n" + "\tStdM: ~p", + [M,Dir,User,SecLevel,EngineID,CtxEngineID,Community,StdM]), + case snmp_test_mgr:start([%% {agent, snmp_test_lib:hostname()}, + {packet_server_debug,true}, + {debug,true}, + {agent, get(master_host)}, + {agent_udp, 4000}, + {trap_udp, 5000}, + {recbuf,65535}, + quiet, + get(vsn), + {community, Community}, + {user, User}, + {sec_level, SecLevel}, + {engine_id, EngineID}, + {context_engine_id, CtxEngineID}, + {dir, Dir}, + {mibs, mibs(StdM, M)}]) of + {ok, _Pid} -> + Res = apply(?MODULE, F, A), + catch snmp_test_mgr:stop(), + Res; + Err -> + io:format("Error starting manager: ~p\n", [Err]), + catch snmp_test_mgr:stop(), + ?line exit({mgr_start, Err}) + end. + + +mibs(StdMibDir,MibDir) -> + [join(StdMibDir, ?v1_2("STANDARD-MIB.bin", "SNMPv2-MIB.bin")), + join(MibDir, "OLD-SNMPEA-MIB.bin"), + join(StdMibDir, "SNMP-FRAMEWORK-MIB"), + join(StdMibDir, "SNMP-MPD-MIB"), + join(StdMibDir, "SNMP-VIEW-BASED-ACM-MIB"), + join(StdMibDir, "SNMP-USER-BASED-SM-MIB"), + join(StdMibDir, "SNMP-TARGET-MIB"), + join(StdMibDir, "SNMP-NOTIFICATION-MIB"), + join(MibDir, "Klas1.bin"), + join(MibDir, "Klas2.bin"), + join(MibDir, "Klas3.bin"), + join(MibDir, "Klas4.bin"), + join(MibDir, "SA-MIB.bin"), + join(MibDir, "TestTrap.bin"), + join(MibDir, "Test1.bin"), + join(MibDir, "Test2.bin"), + join(MibDir, "TestTrapv2.bin")]. + +join(D,F) -> + filename:join(D,F). + +%% string used in index +is(S) -> [length(S) | S]. + +try_test(Func) -> + call(get(mgr_node), ?MODULE, run, [Func, [], []]). + +try_test(Func, A) -> + call(get(mgr_node), ?MODULE, run, [Func, A, []]). + +try_test(Func, A, Opts) -> + call(get(mgr_node), ?MODULE, run, [Func, A, Opts]). + +call(N,M,F,A) -> + ?DBG("call -> entry with~n" + " N: ~p~n" + " M: ~p~n" + " F: ~p~n" + " A: ~p~n" + " when~n" + " get(): ~p", + [N,M,F,A,get()]), + spawn(N, ?MODULE, wait, [self(),get(),M,F,A]), + receive + {done, {'EXIT', Rn}, Loc} -> + ?DBG("call -> returned ~p",[{done, {'EXIT', Rn}, Loc}]), + put(test_server_loc, Loc), + exit(Rn); + {done, Ret, Zed} -> + ?DBG("call -> returned ~p~n",[{done, Ret, Zed}]), + Ret + end. + +wait(From, Env, M, F, A) -> + ?DBG("wait -> entry with ~n" + "\tFrom: ~p~n" + "\tEnv: ~p",[From,Env]), + lists:foreach(fun({K,V}) -> put(K,V) end, Env), + Rn = (catch apply(M, F, A)), + ?DBG("wait -> Rn: ~n~p", [Rn]), + From ! {done, Rn, get(test_server_loc)}, + exit(Rn). + +expect(A,B) -> ok = snmp_test_mgr:expect(A,B). +expect(A,B,C) -> ok = snmp_test_mgr:expect(A,B,C). +expect(A,B,C,D) -> ok = snmp_test_mgr:expect(A,B,C,D). +expect(A,B,C,D,E,F) -> ok = snmp_test_mgr:expect(A,B,C,D,E,F). + +get_req(Id, Vars) -> + ?DBG("get_req -> entry with~n" + "\tId: ~p~n" + "\tVars: ~p",[Id,Vars]), + g(Vars), + ?DBG("get_req -> await response",[]), + {ok, Val} = snmp_test_mgr:get_response(Id, Vars), + ?DBG("get_req -> response: ~p",[Val]), + Val. + +get_next_req(Vars) -> + ?DBG("get_next_req -> entry with Vars '~p', send request",[Vars]), + gn(Vars), + ?DBG("get_next_req -> await response",[]), + Response = snmp_test_mgr:receive_response(), + ?DBG("get_next_req -> response: ~p",[Response]), + Response. + + + +start_node(Name) -> + ?LOG("start_node -> entry with Name: ~p",[Name]), + M = list_to_atom(?HOSTNAME(node())), + ?DBG("start_node -> M: ~p",[M]), + Pa = filename:dirname(code:which(?MODULE)), + ?DBG("start_node -> Pa: ~p",[Pa]), + + Args = case init:get_argument('CC_TEST') of + {ok, [[]]} -> + " -pa /clearcase/otp/libraries/snmp/ebin "; + {ok, [[Path]]} -> + " -pa " ++ Path; + error -> + "" + end, + %% Do not use start_link!!! (the proc that calls this one is tmp) + ?DBG("start_node -> Args: ~p~n",[Args]), + A = Args ++ " -pa " ++ Pa, + case (catch ?START_NODE(Name, A)) of + {ok, Node} -> + %% Tell the test_server to not clean up things it never started. + ?DBG("start_node -> Node: ~p",[Node]), + {ok, Node}; + Else -> + ?ERR("start_node -> failed with(other): Else: ~p",[Else]), + ?line ?FAIL(Else) + end. + + +stop_node(Node) -> + ?LOG("stop_node -> Node: ~p",[Node]), + rpc:cast(Node, erlang, halt, []). + +p(X) -> + io:format(user, X++"\n", []). + +sleep(X) -> + receive + after + X -> ok + end. + +%%%----------------------------------------------------------------- +%%% Configuration +%%%----------------------------------------------------------------- +config(Vsns, MgrDir, AgentDir, MIp, AIp) -> + ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp, + ?TRAP_UDP, AIp, 4000, + "test"), + ?line case update_usm(Vsns, AgentDir) of + true -> + ?line copy_file(filename:join(AgentDir, "usm.conf"), + filename:join(MgrDir, "usm.conf")), + ?line update_usm_mgr(Vsns, MgrDir); + false -> + ?line ok + end, + ?line update_community(Vsns, AgentDir), + ?line update_vacm(Vsns, AgentDir), + ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns), + ?line write_target_params_conf(AgentDir, Vsns), + ?line write_notify_conf(AgentDir), + ok. + +delete_files(Config) -> + Dir = ?config(agent_dir, Config), + {ok, List} = file:list_dir(Dir), + lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end, + List). + +update_usm(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"agentEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"all-rights\", " + "\"all-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"no-rights\", " + "\"no-rights\", zeroDotZero, " + "usmNoAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authMD5\", " + "\"authMD5\", zeroDotZero, " + "usmHMACMD5AuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_md5xxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"authSHA\", " + "\"authSHA\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmNoPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"\"}.\n", []), + ok = io:format(Fid, "{\"mgrEngine\", \"privDES\", " + "\"privDES\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +update_usm_mgr(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),[read,write]), + file:position(Fid, eof), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"passwd_shaxxxxxxxxxx\", \"passwd_desxxxxxx\"}.\n", + []), + file:close(Fid), + true; + false -> + false + end. + +rewrite_usm_mgr(Dir, ShaKey, DesKey) -> + ?line ok = file:rename(filename:join(Dir,"usm.conf"), + filename:join(Dir,"usm.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"usm.conf"),write), + ok = io:format(Fid, "{\"agentEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + ok = io:format(Fid, "{\"mgrEngine\", \"newUser\", " + "\"newUser\", zeroDotZero, " + "usmHMACSHAAuthProtocol, \"\", \"\", " + "usmDESPrivProtocol, \"\", \"\", \"\", " + "\"~s\", \"~s\"}.\n", + [ShaKey, DesKey]), + file:close(Fid). + +reset_usm_mgr(Dir) -> + ?line ok = file:rename(filename:join(Dir,"usm.old"), + filename:join(Dir,"usm.conf")). + + +update_community([v3], _Dir) -> ok; +update_community(_, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{\"no-rights\",\"no-rights\",\"no-rights\",\"\",\"\"}.\n", + []), + file:close(Fid). + + +-define(tDescr_instance, [1,3,6,1,2,1,16,1,0]). +update_vacm(_Vsn, Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"vacm.conf"),[read,write]), + file:position(Fid, eof), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authMD5\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"authSHA\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"privDES\",\"initial\"}.\n",[]), + ok=io:format(Fid,"{vacmSecurityToGroup,usm,\"newUser\",\"initial\"}.\n",[]), + ok = io:format(Fid, "{vacmViewTreeFamily, \"internet\", " + "~w, excluded, null}.\n", [?tDescr_instance]), + file:close(Fid). + + +vacm_ver(v1) -> v1; +vacm_ver(v2) -> v2c; +vacm_ver(v3) -> usm. + + +write_community_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"community.conf"),write), + ok = write_community_conf1(Fid, Confs), + file:close(Fid). + +write_community_conf1(_, []) -> + ok; +write_community_conf1(Fid, [{ComIdx, ComName, SecName, CtxName, TransTag}|Confs]) -> + ok = io:format(Fid, "{\"~s\", \"~s\", \"~s\", \"~s\", \"~s\"}.~n", + [ComIdx, ComName, SecName, CtxName, TransTag]), + write_community_conf1(Fid, Confs). + + +write_target_addr_conf(Dir, Confs) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + ok = write_target_addr_conf1(Fid, Confs), + file:close(Fid). + + +write_target_addr_conf1(_, []) -> + ok; +write_target_addr_conf1(Fid, + [{Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz}|Confs]) -> + ok = io:format(Fid, "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", + [Name, Ip, Port, Timeout, Retry, TagList, ParamName, + EngineId, TMask, MaxMsgSz]), + write_target_addr_conf1(Fid, Confs). + +write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + lists:foreach(fun(Vsn) -> + ok = io:format(Fid, + "{\"~s\", ~w, ~w, 1500, 3, " + "\"std_trap\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, mk_param(Vsn)]), + case Vsn of + v1 -> ok; + v2 -> + ok = io:format(Fid, + "{\"~s.2\",~w,~w,1500,3, " + "\"std_inform\", \"~s\"}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]); + v3 -> + ok = io:format(Fid, + "{\"~s.3\",~w,~w,1500,3, " + "\"std_inform\", \"~s\", " + "\"mgrEngine\", [], 1024}.~n", + [mk_ip(ManagerIp, Vsn), + ManagerIp, UDP, + mk_param(Vsn)]) + end + end, + Vsns), + file:close(Fid). + +mk_param(v1) -> "target_v1"; +mk_param(v2) -> "target_v2"; +mk_param(v3) -> "target_v3". + +mk_ip([A,B,C,D], Vsn) -> + io_lib:format("~w.~w.~w.~w ~w", [A,B,C,D,Vsn]). + + +rewrite_target_addr_conf(Dir,NewPort) -> + TAFile = filename:join(Dir, "target_addr.conf"), + ?DBG("rewrite_target_addr_conf -> read target file info of address config file",[]), + case file:read_file_info(TAFile) of + {ok, _} -> ok; + {error, R} -> ?ERR("failure reading file info of " + "target address config file: ~p",[R]), + ok + end, + + ?line [TrapAddr|Addrs] = + snmp_conf:read(TAFile,fun(R) -> rewrite_target_addr_conf1(R) end), + + ?DBG("rewrite_target_addr_conf -> TrapAddr: ~p",[TrapAddr]), + + NewAddrs = [rewrite_target_addr_conf2(NewPort,TrapAddr)|Addrs], + + ?DBG("rewrite_target_addr_conf -> NewAddrs: ~p",[NewAddrs]), + + ?line ok = file:rename(filename:join(Dir,"target_addr.conf"), + filename:join(Dir,"target_addr.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_addr.conf"),write), + + ?line ok = rewrite_target_addr_conf3(Fid,NewAddrs), + + file:close(Fid). + +rewrite_target_addr_conf1(O) -> + {ok,O}. + +rewrite_target_addr_conf2(NewPort,{Name,Ip,_Port,Timeout,Retry, + "std_trap",EngineId}) -> + ?LOG("rewrite_target_addr_conf2 -> entry with std_trap",[]), + {Name,Ip,NewPort,Timeout,Retry,"std_trap",EngineId}; +rewrite_target_addr_conf2(_NewPort,O) -> + ?LOG("rewrite_target_addr_conf2 -> entry with " + "~n O: ~p",[O]), + O. + + +rewrite_target_addr_conf3(_,[]) -> ok; +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry, + ParamName,EngineId}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(1) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % ParamsName + "\"~s\"}.", % EngineId + [Name,Ip,Port,Timeout,Retry,ParamName,EngineId]), + rewrite_target_addr_conf3(Fid,T); +rewrite_target_addr_conf3(Fid,[{Name,Ip,Port,Timeout,Retry,TagList, + ParamName,EngineId,TMask,MMS}|T]) -> + ?LOG("rewrite_target_addr_conf3 -> write(2) ~s",[ParamName]), + io:format(Fid, + "{\"~s\", " % Name + "~p, " % Ip + "~p, " % Port + "~p, " % Timeout + "~p, " % Retry + "\"~s\", " % TagList + "\"~s\", " % ParamsName + "\"~s\"," % EngineId + "~p, " % TMask + "~p}.", % MMS + [Name,Ip,Port,Timeout,Retry,TagList,ParamName, + EngineId,TMask,MMS]), + rewrite_target_addr_conf3(Fid,T). + +reset_target_addr_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_addr.old"), + filename:join(Dir,"target_addr.conf")). + +write_target_params_conf(Dir, Vsns) -> + {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + lists:foreach(fun(Vsn) -> + MP = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> v3 + end, + SM = if Vsn == v1 -> v1; + Vsn == v2 -> v2c; + Vsn == v3 -> usm + end, + ok = io:format(Fid, "{\"target_~w\", ~w, ~w, " + "\"all-rights\", noAuthNoPriv}.~n", + [Vsn, MP, SM]) + end, + Vsns), + file:close(Fid). + +rewrite_target_params_conf(Dir, SecName, SecLevel) -> + ?line ok = file:rename(filename:join(Dir,"target_params.conf"), + filename:join(Dir,"target_params.old")), + ?line {ok, Fid} = file:open(filename:join(Dir,"target_params.conf"),write), + ?line ok = io:format(Fid, "{\"target_v3\", v3, usm, \"~s\", ~w}.~n", + [SecName, SecLevel]), + file:close(Fid). + +reset_target_params_conf(Dir) -> + ?line ok = file:rename(filename:join(Dir,"target_params.old"), + filename:join(Dir,"target_params.conf")). + +write_notify_conf(Dir) -> + {ok, Fid} = file:open(filename:join(Dir,"notify.conf"),write), + ok = io:format(Fid, "{\"standard trap\", \"std_trap\", trap}.~n", []), + ok = io:format(Fid, "{\"standard inform\", \"std_inform\",inform}.~n", []), + file:close(Fid). + +ver_to_trap_str([v1]) -> "v1"; +ver_to_trap_str([v2]) -> "v2"; +% default is to use the latest snmp version +ver_to_trap_str([v1,v2]) -> "v2". + + + +write_view_conf(Dir) -> + {ok, Fid} = file:open(a(Dir,"view.conf"),write), + ok = io:format(Fid, "{2, [1,3,6], included, null}.~n", []), + ok = io:format(Fid, "{2, ~w, excluded, null}.~n", [?tDescr_instance]), + file:close(Fid). + +a(A,B) -> lists:append(A,B). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +copy_file(From, To) -> + {ok, Bin} = file:read_file(From), + ok = file:write_file(To, Bin). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +display_memory_usage() -> + Info = snmpa:info(snmp_master_agent), + TreeSize = lists_key1search(tree_size_bytes, Info), + ProcMem = lists_key1search(process_memory, Info), + MibDbSize = lists_key1search([db_memory,mib], Info), + NodeDbSize = lists_key1search([db_memory,node], Info), + TreeDbSize = lists_key1search([db_memory,tree], Info), + ?INF("Memory usage: " + "~n Tree size: ~p" + "~n Process memory size: ~p" + "~n Mib db size: ~p" + "~n Node db size: ~p" + "~n Tree db size: ~p", + [TreeSize, ProcMem, MibDbSize, NodeDbSize, TreeDbSize]). + +lists_key1search([], Res) -> + Res; +lists_key1search([Key|Keys], List) when atom(Key), list(List) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + lists_key1search(Keys, Val); + false -> + undefined + end; +lists_key1search(Key, List) when atom(Key) -> + case lists:keysearch(Key, 1, List) of + {value, {Key, Val}} -> + Val; + false -> + undefined + end. + + +regs() -> + lists:sort(registered()). diff --git a/lib/snmp/test/snmp_app_test.erl b/lib/snmp/test/snmp_app_test.erl new file mode 100644 index 0000000000..5c5a5285a0 --- /dev/null +++ b/lib/snmp/test/snmp_app_test.erl @@ -0,0 +1,430 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the snmp application +%%---------------------------------------------------------------------- +-module(snmp_app_test). + +-export([ + all/1, init_suite/1, fin_suite/1, + init_per_testcase/2, fin_per_testcase/2, + + fields/1, + modules/1, + exportall/1, + app_depend/1, + undef_funcs/1, + + start_and_stop/1, + start_and_stop_empty/1, + start_and_stop_with_agent/1, + start_and_stop_with_manager/1, + start_and_stop_with_agent_and_manager/1, + start_epmty_and_then_agent_and_manager_and_stop/1, + start_with_agent_and_then_manager_and_stop/1, + start_with_manager_and_then_agent_and_stop/1 + ]). + + +-include_lib("kernel/include/file.hrl"). +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + fields, + modules, + exportall, + app_depend, + undef_funcs, + start_and_stop + ], + {conf, init_suite, Cases, fin_suite}. + +init_suite(Config) when is_list(Config) -> + ?DISPLAY_SUITE_INFO(), + PrivDir = ?config(priv_dir, Config), + TopDir = filename:join(PrivDir, app), + case file:make_dir(TopDir) of + ok -> + ok; + Error -> + fail({failed_creating_subsuite_top_dir, Error}) + end, + AppFile = + case is_app() of + {ok, File} -> + io:format("File: ~n~p~n", [File]), + snmp:print_version_info(), + File; + {error, Reason} -> + fail(Reason) + end, + [{app_topdir, TopDir}, {app_file, AppFile} | Config]. + + +is_app() -> + is_app(?APPLICATION). + +is_app(App) -> + LibDir = code:lib_dir(App), + File = filename:join([LibDir, "ebin", atom_to_list(App) ++ ".app"]), + case file:consult(File) of + {ok, [{application, App, AppFile}]} -> + {ok, AppFile}; + Error -> + {error, {invalid_format, Error}} + end. + +fin_suite(suite) -> []; +fin_suite(doc) -> []; +fin_suite(Config) when is_list(Config) -> + Config. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Test server callbacks +init_per_testcase(undef_funcs, Config) -> + Config2 = lists:keydelete(watchdog, 1, Config), + [{watchdog, ?WD_START(?MINS(10))} | Config2]; +init_per_testcase(_Case, Config) -> + Config. + +fin_per_testcase(_Case, Config) -> + Config. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +fields(suite) -> + []; +fields(doc) -> + []; +fields(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Fields = [vsn, description, modules, registered, applications], + case check_fields(Fields, AppFile, []) of + [] -> + ok; + Missing -> + fail({missing_fields, Missing}) + end. + +check_fields([], _AppFile, Missing) -> + Missing; +check_fields([Field|Fields], AppFile, Missing) -> + check_fields(Fields, AppFile, check_field(Field, AppFile, Missing)). + +check_field(Name, AppFile, Missing) -> + io:format("checking field: ~p~n", [Name]), + case lists:keymember(Name, 1, AppFile) of + true -> + Missing; + false -> + [Name|Missing] + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +modules(suite) -> + []; +modules(doc) -> + []; +modules(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Mods = key1search(modules, AppFile), + EbinList = get_ebin_mods(snmp), + case missing_modules(Mods, EbinList, []) of + [] -> + ok; + Missing -> + fail({missing_modules, Missing}) + end, + Allowed = [snmpc, + snmpc_lib, + snmpc_misc, + snmpc_mib_gram, + snmpc_mib_to_hrl, + snmpc_tok], + case extra_modules(Mods, EbinList, Allowed, []) of + [] -> + ok; + Extra -> + fail({extra_modules, Extra}) + end, + {ok, Mods}. + +get_ebin_mods(App) -> + LibDir = code:lib_dir(App), + EbinDir = filename:join([LibDir,"ebin"]), + {ok, Files0} = file:list_dir(EbinDir), + Files1 = [lists:reverse(File) || File <- Files0], + [list_to_atom(lists:reverse(Name)) || [$m,$a,$e,$b,$.|Name] <- Files1]. + + +missing_modules([], _Ebins, Missing) -> + Missing; +missing_modules([Mod|Mods], Ebins, Missing) -> + case lists:member(Mod, Ebins) of + true -> + missing_modules(Mods, Ebins, Missing); + false -> + io:format("missing module: ~p~n", [Mod]), + missing_modules(Mods, Ebins, [Mod|Missing]) + end. + + +extra_modules(_Mods, [], Allowed, Extra) -> + Extra--Allowed; +extra_modules(Mods, [Mod|Ebins], Allowed, Extra) -> + case lists:member(Mod, Mods) of + true -> + extra_modules(Mods, Ebins, Allowed, Extra); + false -> + io:format("superfluous module: ~p~n", [Mod]), + extra_modules(Mods, Ebins, Allowed, [Mod|Extra]) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +exportall(suite) -> + []; +exportall(doc) -> + []; +exportall(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Mods = key1search(modules, AppFile), + check_export_all(Mods). + + +check_export_all([]) -> + ok; +check_export_all([Mod|Mods]) -> + case (catch apply(Mod, module_info, [compile])) of + {'EXIT', {undef, _}} -> + check_export_all(Mods); + O -> + case lists:keysearch(options, 1, O) of + false -> + check_export_all(Mods); + {value, {options, List}} -> + case lists:member(export_all, List) of + true -> + fail({export_all, Mod}); + false -> + check_export_all(Mods) + end + end + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +app_depend(suite) -> + []; +app_depend(doc) -> + []; +app_depend(Config) when is_list(Config) -> + AppFile = key1search(app_file, Config), + Apps = key1search(applications, AppFile), + check_apps(Apps). + + +check_apps([]) -> + ok; +check_apps([App|Apps]) -> + case is_app(App) of + {ok, _} -> + check_apps(Apps); + Error -> + throw({error, {missing_app, {App, Error}}}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +undef_funcs(suite) -> + []; +undef_funcs(doc) -> + []; +undef_funcs(Config) when is_list(Config) -> + App = snmp, + AppFile = key1search(app_file, Config), + Mods = key1search(modules, AppFile), + Root = code:root_dir(), + LibDir = code:lib_dir(App), + EbinDir = filename:join([LibDir,"ebin"]), + XRefTestName = undef_funcs_make_name(App, xref_test_name), + {ok, XRef} = xref:start(XRefTestName), + ok = xref:set_default(XRef, + [{verbose,false},{warnings,false}]), + XRefName = undef_funcs_make_name(App, xref_name), + {ok, XRefName} = xref:add_release(XRef, Root, {name,XRefName}), + {ok, App} = xref:replace_application(XRef, App, EbinDir), + {ok, Undefs} = xref:analyze(XRef, undefined_function_calls), + xref:stop(XRef), + analyze_undefined_function_calls(Undefs, Mods, []). + +analyze_undefined_function_calls([], _, []) -> + ok; +analyze_undefined_function_calls([], _, AppUndefs) -> + exit({suite_failed, {undefined_function_calls, AppUndefs}}); +analyze_undefined_function_calls([{{Mod, _F, _A}, _C} = AppUndef|Undefs], + AppModules, AppUndefs) -> + %% Check that this module is our's + case lists:member(Mod,AppModules) of + true -> + {Calling,Called} = AppUndef, + {Mod1,Func1,Ar1} = Calling, + {Mod2,Func2,Ar2} = Called, + io:format("undefined function call: " + "~n ~w:~w/~w calls ~w:~w/~w~n", + [Mod1,Func1,Ar1,Mod2,Func2,Ar2]), + analyze_undefined_function_calls(Undefs, AppModules, + [AppUndef|AppUndefs]); + false -> + io:format("dropping ~p~n", [Mod]), + analyze_undefined_function_calls(Undefs, AppModules, AppUndefs) + end. + +%% This function is used simply to avoid cut-and-paste errors later... +undef_funcs_make_name(App, PostFix) -> + list_to_atom(atom_to_list(App) ++ "_" ++ atom_to_list(PostFix)). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_and_stop(suite) -> + [ + start_and_stop_empty, + start_and_stop_with_agent, + start_and_stop_with_manager, + start_and_stop_with_agent_and_manager, + start_epmty_and_then_agent_and_manager_and_stop, + start_with_agent_and_then_manager_and_stop, + start_with_manager_and_then_agent_and_stop + ]. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_and_stop_empty(suite) -> + []; +start_and_stop_empty(doc) -> + ["Start and stop the application empty (no configured components)"]; +start_and_stop_empty(Config) when is_list(Config) -> + ?line false = ?IS_SNMP_RUNNING(), + + ?line ok = snmp:start(), + + ?line true = ?IS_SNMP_RUNNING(), + + ?line ok = snmp:stop(), + + ?line false = ?IS_SNMP_RUNNING(), + + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_and_stop_with_agent(suite) -> + []; +start_and_stop_with_agent(doc) -> + ["Start and stop the application with the agent pre-configured"]; +start_and_stop_with_agent(Config) when is_list(Config) -> + ?SKIP(not_implemented_yet). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_and_stop_with_manager(suite) -> + []; +start_and_stop_with_manager(doc) -> + ["Start and stop the application with the manager pre-configured"]; +start_and_stop_with_manager(Config) when is_list(Config) -> + ?SKIP(not_implemented_yet). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_and_stop_with_agent_and_manager(suite) -> + []; +start_and_stop_with_agent_and_manager(doc) -> + ["Start and stop the application with both the agent " + "and the manager pre-configured"]; +start_and_stop_with_agent_and_manager(Config) when is_list(Config) -> + ?SKIP(not_implemented_yet). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_epmty_and_then_agent_and_manager_and_stop(suite) -> + []; +start_epmty_and_then_agent_and_manager_and_stop(doc) -> + ["Start the application empty, then start the agent and then " + "the manager and then stop the application"]; +start_epmty_and_then_agent_and_manager_and_stop(Config) when is_list(Config) -> + ?SKIP(not_implemented_yet). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_with_agent_and_then_manager_and_stop(suite) -> + []; +start_with_agent_and_then_manager_and_stop(doc) -> + ["Start the application with the agent pre-configured, " + "then start the manager and then stop the application"]; +start_with_agent_and_then_manager_and_stop(Config) when is_list(Config) -> + ?SKIP(not_implemented_yet). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +start_with_manager_and_then_agent_and_stop(suite) -> + []; +start_with_manager_and_then_agent_and_stop(doc) -> + ["Start the application with the manager pre-configured, " + "then start the agent and then stop the application"]; +start_with_manager_and_then_agent_and_stop(Config) when is_list(Config) -> + ?SKIP(not_implemented_yet). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +fail(Reason) -> + exit({suite_failed, Reason}). + +key1search(Key, L) -> + case lists:keysearch(Key, 1, L) of + undefined -> + fail({not_found, Key, L}); + {value, {Key, Value}} -> + Value + end. diff --git a/lib/snmp/test/snmp_appup_mgr.erl b/lib/snmp/test/snmp_appup_mgr.erl new file mode 100644 index 0000000000..271d6a2847 --- /dev/null +++ b/lib/snmp/test/snmp_appup_mgr.erl @@ -0,0 +1,280 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Simple (snmp) manager used when performing appup tests. +%%---------------------------------------------------------------------- +-module(snmp_appup_mgr). + +-behaviour(snmpm_user). + +-include_lib("snmp/include/STANDARD-MIB.hrl"). +-include_lib("snmp/include/snmp_types.hrl"). + +-export([start/0, start/1, start/2]). +-export([handle_error/3, + handle_agent/4, + handle_pdu/5, + handle_trap/4, + handle_inform/4, + handle_report/4]). +-export([main/2]). + +-record(agent, {host, port, conf}). +-record(state, {timer, reqs, ids, agent}). + +-define(USER_ID, ?MODULE). +-define(REQ_TIMEOUT, 10000). +-define(POLL_TIMEOUT, 5000). +-define(DEFAULT_PORT, 4000). +%% -define(DEFAULT_PORT, 161). + +-define(v1_2(V1,V2), + case get(vsn) of + v1 -> V1; + _ -> V2 + end). + + +start() -> + {ok, AgentHost} = inet:gethostname(), + AgentPort = ?DEFAULT_PORT, + start(AgentHost, AgentPort). + +start(AgentPort) when is_integer(AgentPort) -> + {ok, AgentHost} = inet:gethostname(), + start(AgentHost, AgentPort); +start(AgentHost) when is_list(AgentHost) -> + AgentPort = 161, + start(AgentHost, AgentPort). + +start(AgentHost, AgentPort) + when is_list(AgentHost) and is_integer(AgentPort) -> + ensure_started(snmp), + Pid = erlang:spawn_link(?MODULE, main, [AgentHost, AgentPort]), + receive + {'EXIT', Pid, normal} -> + ok; + {'EXIT', Pid, Reason} -> + {error, {unexpected_exit, Reason}} + end. + +ensure_started(App) -> + case application:start(App) of + ok -> + ok; + {error, {already_started, _}} -> + ok; + {error, Reason} -> + exit(Reason) + end. + +poll_timer() -> + poll_timer(first). + +poll_timer(How) -> + erlang:send_after(?POLL_TIMEOUT, self(), {poll_timeout, How}). + +next_poll_type(first) -> + all; +next_poll_type(all) -> + first. + +main(AgentHost, AgentPort) -> + ok = snmpm:register_user_monitor(?USER_ID, ?MODULE, self()), + AgentConf = [{community, "all-rights"}, + {engine_id, "agentEngine"}, + {sec_level, noAuthNoPriv}, + {version, v1}], + ok = snmpm:register_agent(?USER_ID, AgentHost, AgentPort, AgentConf), + Reqs = [{"sysDescr", get, ?sysDescr_instance}, + {"sysObjectID", get, ?sysObjectID_instance}, + {"sysUpTime", get, ?sysUpTime_instance}], + Agent = #agent{host = AgentHost, port = AgentPort, conf = AgentConf}, + State = #state{timer = poll_timer(), reqs = Reqs, agent = Agent}, + loop(State). + +loop(State) -> + receive + {poll_timeout, How} -> + NewState = handle_poll_timeout(State, How), + loop(NewState#state{timer = poll_timer(next_poll_type(How))}); + + {req_timeout, ReqId} -> + NewState = handle_req_timeout(State, ReqId), + loop(NewState); + + {snmp_callback, Info} -> + NewState = handle_snmp(State, Info), + loop(NewState) + end. + + +handle_poll_timeout(#state{agent = Agent, reqs = [Req|Reqs], ids = IDs} = S, + first) -> + ReqId = handle_req(Agent, [Req]), + S#state{reqs = Reqs ++ [Req], ids = [ReqId|IDs]}; +handle_poll_timeout(#state{agent = Agent, reqs = Reqs, ids = IDs} = S, all) -> + ReqId = handle_req(Agent, Reqs), + S#state{ids = [ReqId|IDs]}. + +handle_req(#agent{host = Host, port = Port}, Reqs) -> + Oids = [Oid || {_Desc, Op, Oid} <- Reqs, Op == get], + Descs = [Desc || {Desc, Op, _Oid} <- Reqs, Op == get], + {ok, ReqId} = snmpm:ag(?USER_ID, Host, Port, Oids), + p("issued get-request (~w) for: ~s", [ReqId, oid_descs(Descs)]), + ReqTimer = erlang:send_after(?REQ_TIMEOUT, self(), {req_timeout, ReqId}), + {ReqId, erlang:now(), ReqTimer}. + +oid_descs([]) -> + []; +oid_descs([Desc]) -> + lists:flatten(io_lib:format("~s", [Desc])); +oid_descs([Desc|Descs]) -> + lists:flatten(io_lib:format("~s, ", [Desc])) ++ oid_descs(Descs). + +handle_req_timeout(#state{ids = IDs0} = State, ReqId) -> + case lists:keysearch(ReqId, 1, IDs0) of + {value, {ReqId, _T, _Ref}} -> + e("Request timeout for request ~w", [ReqId]), + IDs = lists:keydelete(ReqId, 1, IDs0), + State#state{ids = IDs}; + false -> + w("Did not find request corresponding to id ~w", [ReqId]), + State + end. + +handle_snmp(#state{ids = IDs0} = S, {error, ReqId, Reason}) -> + case lists:keysearch(ReqId, 1, IDs0) of + {value, {ReqId, T, Ref}} -> + Diff = timer:now_diff(erlang:now(), T), + p("SNMP error regarding outstanding request after ~w microsec:" + "~n ReqId: ~w" + "~n Reason: ~w", [Diff, ReqId, Reason]), + IDs = lists:keydelete(ReqId, 1, IDs0), + erlang:cancel_timer(Ref), + S#state{ids = IDs}; + false -> + w("SNMP error regarding unknown request:" + "~n ReqId: ~w" + "~n Reason: ~w", [ReqId, Reason]), + S + end; + +handle_snmp(State, {agent, Addr, Port, SnmpInfo}) -> + p("Received agent info:" + "~n Addr: ~w" + "~n Port: ~w" + "~n SnmpInfo: ~w", [Addr, Port, SnmpInfo]), + State; + +handle_snmp(#state{ids = IDs0} = S, {pdu, Addr, Port, ReqId, SnmpResponse}) -> + case lists:keysearch(ReqId, 1, IDs0) of + {value, {ReqId, T, Ref}} -> + Diff = timer:now_diff(erlang:now(), T), + p("SNMP pdu regarding outstanding request after ~w microsec:" + "~n ReqId: ~w" + "~n Addr: ~w" + "~n Port: ~w" + "~n SnmpResponse: ~w", + [Diff, ReqId, Addr, Port, SnmpResponse]), + IDs = lists:keydelete(ReqId, 1, IDs0), + erlang:cancel_timer(Ref), + S#state{ids = IDs}; + false -> + w("SNMP pdu regarding unknown request:" + "~n ReqId: ~w" + "~n Addr: ~w" + "~n Port: ~w" + "~n SnmpResponse: ~w", [ReqId, Addr, Port, SnmpResponse]), + S + end; + +handle_snmp(State, {trap, Addr, Port, SnmpTrapInfo}) -> + p("Received trap:" + "~n Addr: ~w" + "~n Port: ~w" + "~n SnmpTrapInfo: ~w", [Addr, Port, SnmpTrapInfo]), + State; + +handle_snmp(State, {inform, Addr, Port, SnmpInform}) -> + p("Received inform:" + "~n Addr: ~w" + "~n Port: ~w" + "~n SnmpInform: ~w", [Addr, Port, SnmpInform]), + State; + +handle_snmp(State, {report, Addr, Port, SnmpReport}) -> + p("Received report:" + "~n Addr: ~w" + "~n Port: ~w" + "~n SnmpReport: ~w", [Addr, Port, SnmpReport]), + State; + +handle_snmp(State, Unknown) -> + p("Received unknown snmp info:" + "~n Unknown: ~w", [Unknown]), + State. + + +%% ----------------------------------------------------------------------- +%% +%% Manager user callback API +%% +%% ----------------------------------------------------------------------- + + +handle_error(ReqId, Reason, Pid) -> + Pid ! {snmp_callback, {error, ReqId, Reason}}, + ignore. + +handle_agent(Addr, Port, SnmpInfo, Pid) -> + Pid ! {snmp_callback, {agent, Addr, Port, SnmpInfo}}, + ignore. + +handle_pdu(Addr, Port, ReqId, SnmpResponse, Pid) -> + Pid ! {snmp_callback, {pdu, Addr, Port, ReqId, SnmpResponse}}, + ignore. + +handle_trap(Addr, Port, SnmpTrapInfo, Pid) -> + Pid ! {snmp_callback, {trap, Addr, Port, SnmpTrapInfo}}, + ignore. + +handle_inform(Addr, Port, SnmpInform, Pid) -> + Pid ! {snmp_callback, {inform, Addr, Port, SnmpInform}}, + ignore. + +handle_report(Addr, Port, SnmpReport, Pid) -> + Pid ! {snmp_callback, {report, Addr, Port, SnmpReport}}, + ignore. + + +%% ----------------------------------------------------------------------- + +e(F, A) -> + p("*** ERROR ***", F, A). + +w(F, A) -> + p("*** WARNING ***", F, A). + +p(F, A) -> + p("*** INFO ***", F, A). + +p(P, F, A) -> + io:format("~s~nMGR: " ++ F ++ "~n~n", [P|A]). diff --git a/lib/snmp/test/snmp_appup_test.erl b/lib/snmp/test/snmp_appup_test.erl new file mode 100644 index 0000000000..18509526cf --- /dev/null +++ b/lib/snmp/test/snmp_appup_test.erl @@ -0,0 +1,560 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Verify the application specifics of the Megaco application +%%---------------------------------------------------------------------- +-module(snmp_appup_test). + +-export([ + all/1, init_suite/1, fin_suite/1, + init_per_testcase/2, fin_per_testcase/2, + + appup_file/1 + + ]). + +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +all(suite) -> + Cases = + [ + appup_file + ], + {conf, init_suite, Cases, fin_suite}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +init_suite(suite) -> []; +init_suite(doc) -> []; +init_suite(Config) when is_list(Config) -> + PrivDir = ?config(priv_dir, Config), + TopDir = filename:join(PrivDir, appup), + case file:make_dir(TopDir) of + ok -> + ok; + Error -> + fail({failed_creating_subsuite_top_dir, Error}) + end, + AppFile = file_name(?APPLICATION, ".app"), + AppupFile = file_name(?APPLICATION, ".appup"), + [{app_file, AppFile}, + {appup_file, AppupFile}, + {appup_topdir, TopDir} | Config]. + + +file_name(App, Ext) -> + Env = init:get_arguments(), + LibDir = + case lists:keysearch(clearcase, 1, Env) of + false -> + code:lib_dir(App); + _ -> + ".." + end, + filename:join([LibDir, "ebin", atom_to_list(App) ++ Ext]). + + +fin_suite(suite) -> []; +fin_suite(doc) -> []; +fin_suite(Config) when is_list(Config) -> + Config. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Test server callbacks +init_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Config. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +appup_file(suite) -> + []; +appup_file(doc) -> + "Perform a simple check of the appup file"; +appup_file(Config) when is_list(Config) -> + AppupFile = key1search(appup_file, Config), + AppFile = key1search(app_file, Config), + Modules = modules(AppFile), + check_appup(AppupFile, Modules). + +modules(File) -> + case file:consult(File) of + {ok, [{application,snmp,Info}]} -> + case lists:keysearch(modules,1,Info) of + {value, {modules, Modules}} -> + Modules; + false -> + fail({bad_appinfo, Info}) + end; + Error -> + fail({bad_appfile, Error, File}) + end. + + +check_appup(AppupFile, Modules) -> + case file:consult(AppupFile) of + {ok, [{V, UpFrom, DownTo}]} -> + check_appup(V, UpFrom, DownTo, Modules); + Else -> + fail({bad_appupfile, Else}) + end. + + +check_appup(V, UpFrom, DownTo, Modules) -> + check_version(V), + check_depends(up, UpFrom, Modules), + check_depends(down, DownTo, Modules), + check_module_subset(up, UpFrom), + check_module_subset(down, DownTo), + ok. + +check_depends(_, [], _) -> + ok; +check_depends(UpDown, [Dep|Deps], Modules) -> + check_depend(UpDown, Dep, Modules), + check_depends(UpDown, Deps, Modules). + + +check_depend(up = UpDown, {add_application, ?APPLICATION} = Instr, Modules) -> + d("check_instructions(~w) -> entry with" + "~n Instruction: ~p" + "~n Modules: ~p", [UpDown, Instr, Modules]), + ok; +check_depend(down = UpDown, {remove_application, ?APPLICATION} = Instr, + Modules) -> + d("check_instructions(~w) -> entry with" + "~n Instruction: ~p" + "~n Modules: ~p", [UpDown, Instr, Modules]), + ok; +check_depend(UpDown, {V, Instructions}, Modules) -> + d("check_instructions(~w) -> entry with" + "~n V: ~p" + "~n Modules: ~p", [UpDown, V, Modules]), + check_version(V), + case check_instructions(UpDown, + Instructions, Instructions, [], [], Modules) of + {_Good, []} -> + ok; + {_, Bad} -> + fail({bad_instructions, Bad, UpDown}) + end. + + +check_instructions(_, [], _, Good, Bad, _) -> + {lists:reverse(Good), lists:reverse(Bad)}; +check_instructions(UpDown, [Instr|Instrs], AllInstr, Good, Bad, Modules) -> + d("check_instructions(~w) -> entry with" + "~n Instr: ~p", [UpDown,Instr]), + case (catch check_instruction(UpDown, Instr, AllInstr, Modules)) of + ok -> + check_instructions(UpDown, Instrs, AllInstr, + [Instr|Good], Bad, Modules); + {error, Reason} -> + check_instructions(UpDown, Instrs, AllInstr, Good, + [{Instr, Reason}|Bad], Modules) + end; +check_instructions(UpDown, Instructions, _, _, _, _) -> + fail({bad_instructions, {UpDown, Instructions}}). + +check_instruction(_, {restart_application, ?APPLICATION}, _, _Modules) -> + d("check_instruction -> entry when restart_application instruction"), + ok; + +%% A new module is added +check_instruction(up, {add_module, Module}, _, Modules) + when is_atom(Module) -> + d("check_instruction -> entry when up-add_module instruction with" + "~n Module: ~p", [Module]), + check_module(Module, Modules); + +%% An old module is re-added +check_instruction(down, {add_module, Module}, _, Modules) + when is_atom(Module) -> + d("check_instruction -> entry when down-add_module instruction with" + "~n Module: ~p", [Module]), + case (catch check_module(Module, Modules)) of + {error, {unknown_module, Module, Modules}} -> + ok; + ok -> + error({existing_readded_module, Module}) + end; + +check_instruction(up, {delete_module, Module}, _, Modules) + when is_atom(Module) -> + d("check_instruction -> entry when up-delete_module instruction with" + "~n Module: ~p", [Module]), + case (catch check_module(Module, Modules)) of + {error, {unknown_module, Module, Modules}} -> + ok; + ok -> + error({module_cannot_be_deleted, Module}) + end; + +%% An new module is deleted +check_instruction(down, {delete_module, Module}, _, Modules) + when is_atom(Module) -> + d("check_instruction -> entry when down-delete_module instruction with" + "~n Module: ~p", [Module]), + check_module(Module, Modules); + +%% Removing a module on upgrade: +%% - the module has been removed from the app-file. +%% - check that no module depends on this (removed) module +check_instruction(up, {remove, {Module, Pre, Post}}, _, Modules) + when is_atom(Module) and is_atom(Pre) and is_atom(Post) -> + d("check_instruction -> entry when up-remove instruction with" + "~n Module: ~p" + "~n Pre: ~p" + "~n Post: ~p", [Module, Pre, Post]), + case (catch check_module(Module, Modules)) of + {error, {unknown_module, Module, Modules}} -> + check_purge(Pre), + check_purge(Post); + ok -> + error({existing_removed_module, Module}) + end; + +%% Removing a module on downgrade: the module exist +%% in the app-file. +check_instruction(down, {remove, {Module, Pre, Post}}, AllInstr, Modules) + when is_atom(Module) and is_atom(Pre) and is_atom(Post) -> + d("check_instruction -> entry when down-remove instruction with" + "~n Module: ~p" + "~n Pre: ~p" + "~n Post: ~p", [Module, Pre, Post]), + case (catch check_module(Module, Modules)) of + ok -> + check_purge(Pre), + check_purge(Post), + check_no_remove_depends(Module, AllInstr); + {error, {unknown_module, Module, Modules}} -> + error({nonexisting_removed_module, Module}) + end; + +check_instruction(_, {load_module, Module, Pre, Post, Depend}, + AllInstr, Modules) + when is_atom(Module) and + is_atom(Pre) and + is_atom(Post) and + is_list(Depend) -> + d("check_instruction -> entry when load_module instruction with" + "~n Module: ~p" + "~n Pre: ~p" + "~n Post: ~p" + "~n Depend: ~p", [Module, Pre, Post, Depend]), + check_module(Module, Modules), + check_module_depend(Module, Depend, Modules), + check_module_depend(Module, Depend, updated_modules(AllInstr, [])), + check_purge(Pre), + check_purge(Post); + +check_instruction(_, {update, Module, Change, Pre, Post, Depend}, + AllInstr, Modules) + when is_atom(Module) and + is_atom(Pre) and + is_atom(Post) and + is_list(Depend) -> + d("check_instruction -> entry when update instruction with" + "~n Module: ~p" + "~n Change: ~p" + "~n Pre: ~p" + "~n Post: ~p" + "~n Depend: ~p", [Module, Change, Pre, Post, Depend]), + check_module(Module, Modules), + check_module_depend(Module, Depend, Modules), + check_module_depend(Module, Depend, updated_modules(AllInstr, [])), + check_change(Change), + check_purge(Pre), + check_purge(Post); + +check_instruction(_, {update, Module, supervisor}, _, Modules) + when is_atom(Module) -> + d("check_instruction -> entry when supervisor update instruction with" + "~n Module: ~p", [Module]), + check_module(Module, Modules); + +check_instruction(_, {apply, {Module, Function, Args}}, _, _Modules) + when is_atom(Module) and is_atom(Function) and is_list(Args) -> + d("check_instruction -> entry when apply instruction with" + "~n Module: ~p" + "~n Function: ~p" + "~n Args: ~p", [Module, Function, Args]), + check_apply(Module, Function, Args); + +check_instruction(_, Instr, _AllInstr, _Modules) -> + error({error, {unknown_instruction, Instr}}). + +%% If Module X depends on Module Y, then module Y must have an update +%% instruction of some sort (otherwise the depend is faulty). +updated_modules([], Modules) -> + d("updated_modules -> entry when done with" + "~n Modules: ~p", [Modules]), + Modules; +updated_modules([Instr|Instrs], Modules) -> + d("updated_modules -> entry with" + "~n Instr: ~p" + "~n Modules: ~p", [Instr,Modules]), + case instruction_module(Instr) of + {module, Module} -> + d("updated_modules -> Module: ~p", [Module]), + updated_modules(Instrs, [Module|Modules]); + no_module -> + updated_modules(Instrs, Modules) + end. + +instruction_module({add_module, Module}) -> + {module, Module}; +instruction_module({delete_module, Module}) -> + {module, Module}; +instruction_module({remove, {Module, _, _}}) -> + {module, Module}; +instruction_module({load_module, Module, _, _, _}) -> + {module, Module}; +instruction_module({update, Module, _, _, _, _}) -> + {module, Module}; +instruction_module({update, Module, _}) -> + {module, Module}; +instruction_module({apply, {_, _, _}}) -> + no_module; +instruction_module(Instr) -> + d("instruction_module -> entry when unknown instruction with" + "~n Instr: ~p", [Instr]), + error({error, {unknown_instruction, Instr}}). + + +%% Check that the modules handled in an instruction set for version X +%% is a subset of the instruction set for version X-1. +check_module_subset(Direction, Instructions) -> + d("check_module_subset(~w) -> entry when" + "~n Instructions: ~p", [Direction,Instructions]), + do_check_module_subset(modules_of(Instructions)). + +do_check_module_subset([]) -> + ok; +do_check_module_subset([_]) -> + ok; +do_check_module_subset([{_V1, Mods1}|T]) -> + d("do_check_module_subset -> entry with" + "~n V1: ~s" + "~n Mods1: ~p", [_V1, Mods1]), + {V2, Mods2} = hd(T), + d("do_check_module_subset -> " + "~n V2: ~s" + "~n Mods2: ~p", [V2, Mods2]), + %% Check that the modules in V1 is a subset of V2 + case do_check_module_subset2(Mods1, Mods2) of + ok -> + do_check_module_subset(T); + {error, Modules} -> + fail({subset_missing_instructions, V2, Modules}) + end. + +do_check_module_subset2(_Mods1, [{restart_application, ?APPLICATION}]) -> + ok; +do_check_module_subset2(Mods1, Mods2) -> + do_check_module_subset2(Mods1, Mods2, []). + +do_check_module_subset2([], _, []) -> + ok; +do_check_module_subset2([], _, Acc) -> + {error, lists:reverse(Acc)}; +do_check_module_subset2([Mod|Mods], Mods2, Acc) -> + case lists:member(Mod, Mods2) of + true -> + do_check_module_subset2(Mods, Mods2, Acc); + false -> + do_check_module_subset2(Mods, Mods2, [Mod|Acc]) + end. + + +modules_of(Instructions) -> + modules_of(Instructions, []). + +modules_of([], Acc) -> + lists:reverse(Acc); +modules_of([{_V,[{restart_application, ?APPLICATION}]}|T], Acc) -> + modules_of(T, Acc); +modules_of([{V,Instructions}|T], Acc) -> + Mods = modules_of2(Instructions, []), + modules_of(T, [{V, Mods}|Acc]). + +modules_of2([], Acc) -> + lists:reverse(Acc); +modules_of2([Instr|Instructions], Acc) -> + d("module_of -> entry with" + "~n Instr: ~p", [Instr]), + case module_of(Instr) of + {value, Mod} -> + d("module_of -> Mod: ~p", [Mod]), + modules_of2(Instructions, [Mod|Acc]); + false -> + modules_of2(Instructions, Acc) + end. + +module_of({add_module, Module}) -> + {value, Module}; +module_of({delete_module, Module}) -> + {value, Module}; +module_of({remove, {Module, _Pre, _Post}}) -> + {value, Module}; +module_of({load_module, Module, _Pre, _Post, _Depend}) -> + {value, Module}; +module_of({update, Module, _Change, _Pre, _Post, _Depend}) -> + {value, Module}; +module_of({update, Module, supervisor}) -> + {value, Module}; +module_of(_) -> + false. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +check_version(V) when is_list(V) -> + ok; +check_version(V) -> + error({bad_version, V}). + + +check_module(M, Modules) when is_atom(M) -> + case lists:member(M, Modules) of + true -> + ok; + false -> + error({unknown_module, M, Modules}) + end; +check_module(M, _) -> + error({bad_module, M}). + + +check_module_depend(M, [], _) when is_atom(M) -> + ok; +check_module_depend(M, Deps, Modules) when is_atom(M) and is_list(Deps) -> + case [Dep || Dep <- Deps, lists:member(Dep, Modules) == false] of + [] -> + ok; + Unknown -> + error({unknown_depend_modules, Unknown}) + end; +check_module_depend(_M, D, _Modules) -> + error({bad_depend, D}). + + +check_no_remove_depends(_Module, []) -> + ok; +check_no_remove_depends(Module, [Instr|Instrs]) -> + check_no_remove_depend(Module, Instr), + check_no_remove_depends(Module, Instrs). + +check_no_remove_depend(Module, {load_module, Mod, _Pre, _Post, Depend}) -> + case lists:member(Module, Depend) of + true -> + error({removed_module_in_depend, load_module, Mod, Module}); + false -> + ok + end; +check_no_remove_depend(Module, {update, Mod, _Change, _Pre, _Post, Depend}) -> + case lists:member(Module, Depend) of + true -> + error({removed_module_in_depend, update, Mod, Module}); + false -> + ok + end; +check_no_remove_depend(_, _) -> + ok. + + +check_change(soft) -> + ok; +check_change({advanced, _Something}) -> + ok; +check_change(Change) -> + error({bad_change, Change}). + + +check_purge(soft_purge) -> + ok; +check_purge(brutal_purge) -> + ok; +check_purge(Purge) -> + error({bad_purge, Purge}). + +check_apply(Module, Function, Args) -> + case (catch Module:module_info()) of + Info when is_list(Info) -> + check_exported(Function, Args, Info); + {'EXIT', {undef, _}} -> + error({not_existing_module, Module}) + end. + +check_exported(Function, Args, Info) -> + case lists:keysearch(exports, 1, Info) of + {value, {exports, FuncList}} -> + Arity = length(Args), + Arities = [A || {F, A} <- FuncList, F == Function], + case lists:member(Arity, Arities) of + true -> + ok; + false -> + fail({not_exported_function, Function, Arity}) + end; + _ -> + error({bad_export, Info}) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +error(Reason) -> + throw({error, Reason}). + +fail(Reason) -> + exit({suite_failed, Reason}). + +key1search(Key, L) -> + case lists:keysearch(Key, 1, L) of + undefined -> + fail({not_found, Key, L}); + {value, {Key, Value}} -> + Value + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +d(F) -> + d(F, []). + +d(F, A) -> + d(true, F, A). + +d(true, F, A) -> + io:format(F ++ "~n", A); +d(_, _, _) -> + ok. + diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl new file mode 100644 index 0000000000..9a9127a130 --- /dev/null +++ b/lib/snmp/test/snmp_compiler_test.erl @@ -0,0 +1,391 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Test the snmp mib compiler +%% +%% Run test: ts:run(snmp, snmp_compiler_test, [batch]). +%% +%%---------------------------------------------------------------------- +-module(snmp_compiler_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-include_lib("snmp/include/snmp_types.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + all/1, + init_per_testcase/2, fin_per_testcase/2, + + description/1, + oid_conflicts/1, + imports/1, + module_identity/1, + + tickets/1, + otp_6150/1 + + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + ]). + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(_Case, Config) when is_list(Config) -> + Dir = ?config(priv_dir, Config), + DataDir = ?config(data_dir, Config), + [_|RL] = lists:reverse(filename:split(DataDir)), + MibDir = join(lists:reverse(["snmp_test_data"|RL])), + CompDir = join(Dir, "comp_dir/"), + ?line ok = file:make_dir(CompDir), + [{comp_dir, CompDir},{mib_dir, MibDir}|Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + CompDir = ?config(comp_dir, Config), + ?line ok = ?DEL_DIR(CompDir), + lists:keydelete(comp_dir, 1, Config). + + +%%====================================================================== +%% Test case definitions +%%====================================================================== + +all(suite) -> + [ + description, + oid_conflicts, + imports, + module_identity, + tickets + ]. + +tickets(suite) -> + [ + otp_6150 + ]. + + +%%====================================================================== +%% Test functions +%%====================================================================== + +description(suite) -> []; +description(Config) when is_list(Config) -> + put(tname,desc), + p("starting with Config: ~p~n", [Config]), + + Dir = ?config(comp_dir, Config), + Filename = join(Dir,"test"), + MibSrcName = Filename ++ ".mib", + MibBinName = Filename ++ ".bin", + Desctext = "This is a test description", + Oid = [1,3,6,1,2,1,15,1], + write_mib(MibSrcName,Desctext), + ?line {ok,_} = snmpc:compile(MibSrcName, [{outdir, Dir}, + {group_check, false}, + {warnings, false}, + {description, false}]), + MIB1 = read_mib(MibBinName), + %% io:format("description -> MIB1: ~n~p~n", [MIB1]), + check_mib(MIB1#mib.mes, Oid, undefined), + ?line {ok,_} = snmpc:compile(MibSrcName, [{outdir, Dir}, + {group_check, false}, + {warnings, false}, + {description, true}]), + MIB2 = read_mib(MibBinName), + %% io:format("description -> MIB2: ~n~p~n", [MIB2]), + check_mib(MIB2#mib.mes, Oid, Desctext), + + %% Cleanup + file:delete(MibSrcName), + file:delete(MibBinName), + ok. + + +oid_conflicts(suite) -> []; +oid_conflicts(Config) when is_list(Config) -> + put(tname,oid_conflicts), + p("starting with Config: ~p~n", [Config]), + + Dir = ?config(comp_dir, Config), + Mib = join(Dir,"TESTv2.mib"), + ?line ok = write_oid_conflict_mib(Mib), + ?line {error,compilation_failed} = + snmpc:compile(Mib,[{outdir, Dir},{verbosity,trace}]), + ok. + + +imports(suite) -> + []; +imports(Config) when is_list(Config) -> + ?SKIP(not_yet_implemented). + + +module_identity(suite) -> + []; +module_identity(Config) when is_list(Config) -> + ?SKIP(not_yet_implemented). + + +otp_6150(suite) -> + []; +otp_6150(Config) when is_list(Config) -> + put(tname,otp_6150), + p("starting with Config: ~p~n", [Config]), + + Dir = ?config(comp_dir, Config), + MibDir = ?config(mib_dir, Config), + MibFile = join(MibDir, "ERICSSON-TOP-MIB.mib"), + ?line {ok, Mib} = snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]), + io:format("otp_6150 -> Mib: ~n~p~n", [Mib]), + ok. + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +write_oid_conflict_mib(Filename) -> + MibText = "TESTv2 DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + Integer32, snmpModules ,experimental + FROM SNMPv2-SMI + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF + DisplayString + FROM SNMPv2-TC + RowStatus + FROM STANDARD-MIB; + + +exampleModule MODULE-IDENTITY +LAST-UPDATED \"0005290000Z\" + ORGANIZATION \"Erlang\" + CONTACT-INFO \" test mib + Ericsson Utvecklings AB +Open System +Box 1505 +SE-125 25 �LVSJ�\" + +DESCRIPTION +\" Objects for management \" + REVISION \"0005290000Z\" + DESCRIPTION +\"The initial version\" + ::= { snmpModules 1 } + +example1 OBJECT IDENTIFIER ::= { experimental 7} +-- example2 OBJECT IDENTIFIER ::= { experimental 7} + + +myName OBJECT-TYPE +SYNTAX DisplayString +MAX-ACCESS read-write +STATUS current +DESCRIPTION +\"My own name\" + ::= { example1 1 } + +myNotification NOTIFICATION-TYPE +STATUS current +DESCRIPTION +\"test trap.\" + ::= { example1 1 } + +friendsTable OBJECT-TYPE +SYNTAX SEQUENCE OF FriendsEntry +MAX-ACCESS not-accessible +STATUS current +DESCRIPTION +\"A list of friends.\" + ::= { example1 4 } + +friendsEntry OBJECT-TYPE +SYNTAX FriendsEntry +MAX-ACCESS not-accessible +STATUS current +DESCRIPTION +\"\" + INDEX { fIndex } +::= { friendsTable 1 } + +FriendsEntry ::= SEQUENCE { + fIndex INTEGER, + fName DisplayString, + fAddress DisplayString, + fStatus RowStatus + } + +fIndex OBJECT-TYPE +SYNTAX INTEGER +MAX-ACCESS read-only +STATUS current +DESCRIPTION +\"number of friend\" + ::= { friendsEntry 1 } + +fName OBJECT-TYPE +SYNTAX DisplayString (SIZE (0..255)) +MAX-ACCESS read-write +STATUS current +DESCRIPTION +\"Name of a friend\" + ::= { friendsEntry 2 } + +fAddress OBJECT-TYPE +SYNTAX DisplayString (SIZE (0..255)) +MAX-ACCESS read-write +STATUS current +DESCRIPTION +\"Address of a friend\" + ::= { friendsEntry 3 } + +fStatus OBJECT-TYPE +SYNTAX RowStatus +MAX-ACCESS read-write +STATUS current +DESCRIPTION +\"The status of this conceptual row.\" + ::= { friendsEntry 4 } + +-- myName2 OBJECT IDENTIFIER ::= { example1 1 } + +friendGroup OBJECT-GROUP +OBJECTS { myName, fIndex, fName,fAddress, fStatus } +STATUS current +DESCRIPTION \" A object group\" + ::= { example1 2 } + +myNotificationGroup NOTIFICATION-GROUP +NOTIFICATIONS { myNotification } +STATUS current +DESCRIPTION +\"Test notification group\" + ::= { example1 3 } +END", + + file:write_file(Filename, MibText). + + +write_mib(Filename,Desc) -> + Binary = "Test DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, + snmpModules, mib-2 + FROM SNMPv2-SMI ; + +snmpMIB MODULE-IDENTITY +LAST-UPDATED \"9511090000Z\" + ORGANIZATION \"\" + CONTACT-INFO \"\" + DESCRIPTION +::= { snmpModules 1 } + + +test OBJECT IDENTIFIER ::= { mib-2 15 } + +bits1 OBJECT-TYPE +SYNTAX BITS { b0(0), b1(1), b2(2) } +MAX-ACCESS read-write +STATUS current +DESCRIPTION \"" ++ Desc ++ "\" + ::= { test 1 } + +END", + Message = file:write_file(Filename ,Binary), +case Message of + ok -> ok; + {error, Reason} -> + exit({failed_writing_mib,Reason}) +end. + + +read_mib(Filename) -> + case file:read_file(Filename) of + {ok,Bin} -> + binary_to_term(Bin); + {error,Reason} -> + exit({failed_reading_mib,Filename,Reason}) + end. + +check_mib([],_,_) -> + not_found; +check_mib([#me{oid = Oid, description = Description}| _T], Oid, Testdata) -> + check_desc(Description, Testdata); +check_mib([_H|T], Oid, Testdata ) -> + check_mib(T, Oid, Testdata ). + +check_desc(Desc, Desc) -> + ok; +check_desc(Desc1, Desc2) -> + exit({'description not equal', Desc1, Desc2}). + + +join(Comp) -> + filename:join(Comp). + +join(A,B) -> + filename:join(A,B). + + +%% ------ + +%% p(F) -> +%% p(F, []). + +p(F, A) -> + p(get(tname), F, A). + +p(TName, F, A) -> + io:format("*** [~w][~s] ***" + "~n" ++ F ++ "~n", [TName,format_timestamp(now())|A]). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + diff --git a/lib/snmp/test/snmp_conf_test.erl b/lib/snmp/test/snmp_conf_test.erl new file mode 100644 index 0000000000..d2f9631947 --- /dev/null +++ b/lib/snmp/test/snmp_conf_test.erl @@ -0,0 +1,680 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%%---------------------------------------------------------------------- +%% Purpose: +%%---------------------------------------------------------------------- +-module(snmp_conf_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). + +-include_lib("snmp/include/STANDARD-MIB.hrl"). +-include_lib("snmp/include/OTP-SNMPEA-MIB.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + all/1, + init_per_testcase/2, fin_per_testcase/2, + + check_mandatory/1, + check_integer1/1, + check_integer2/1, + check_string1/1, + check_string2/1, + check_atom/1, + check_ip/1, + check_taddress/1, + check_packet_size/1, + check_oid/1, + check_sec_model1/1, + check_sec_model2/1, + check_sec_level/1, + check_timer/1, + + read/1, + read_files/1 + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + ]). + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +%%====================================================================== +%% Test case definitions +%%====================================================================== +all(suite) -> + [ + check_mandatory, + check_integer1, + check_integer2, + check_string1, + check_string2, + check_atom, + check_ip, + check_taddress, + check_packet_size, + check_oid, + check_sec_model1, + check_sec_model2, + check_sec_level, + check_timer, + + read, + read_files + ]. + + +%%====================================================================== +%% Test functions +%%====================================================================== + +check_mandatory(suite) -> []; +check_mandatory(Config) when is_list(Config) -> + ?P(check_mandatory), + %% d("check_mandatory -> entry"), + A1 = [{a, hej}, {b, hopp}, {c, 10}, {d, 10101}, {f, 10.88}], + B1 = [{a, {value, hejsan}}, + {b, mandatory}, + {d, {value, 20202}}, + {e, {value, "kalle"}}], + ?line {ok, L1} = verify_mandatory(A1, B1), + ?DBG("check_mandatory -> L1: ~p", [L1]), + A2 = [{a, hej}, {c, 10}, {d, 10101}, {f, 10.88}], + B2 = [{a, {value, hejsan}}, + {b, mandatory}, + {d, {value, 20202}}, + {e, {value, "kalle"}}], + ?line ok = verify_not_mandatory(A2, B2), + ok. + +verify_mandatory(A, B) -> + case (catch snmp_conf:check_mandatory(A, B)) of + {'EXIT', Reason} -> + ?FAIL({mandatory_fail, A, B, Reason}); + {ok, A} -> + ?FAIL({mandatory_not_updated, A, B}); + {ok, L} when A /= L -> + verify_mandatory2(B, L) + end. + +verify_mandatory2([], L) -> + {ok, L}; +verify_mandatory2([{Key, _}|T], L) -> + case lists:keysearch(Key, 1, L) of + false -> + ?FAIL({missing_key, Key, L}); + {value, _} -> + verify_mandatory2(T, L) + end. + +verify_not_mandatory(A, B) -> + case (catch snmp_conf:check_mandatory(A, B)) of + {error, _Reason} -> + ok; + Else -> + ?FAIL({mandatory_not_fail, Else}) + end. + + +%%====================================================================== + +check_integer1(suite) -> []; +check_integer1(Config) when is_list(Config) -> + ?P(check_integer1), + ?line ok = verify_int(0), + ?line ok = verify_int(16#FF), + ?line ok = verify_int(16#FFFF), + ?line ok = verify_int(16#FFFFFFFF), + ?line ok = verify_int(-1), + ?line ok = verify_int(-333), + + ?line ok = verify_not_int("kalle & hobbe"), + ?line ok = verify_not_int(kalle_och_hobbe), + ?line ok = verify_not_int(1.5), + + ok. + +verify_int(Val) -> + case (catch snmp_conf:check_integer(Val)) of + {error, Reason} -> + ?FAIL({verify_int, Val, Reason}); + ok -> + ok + end. + +verify_not_int(Val) -> + case (catch snmp_conf:check_integer(Val)) of + ok -> + ?FAIL({verify_int, Val}); + {error, _Reason} -> + ok + end. + +%%====================================================================== + +check_integer2(suite) -> []; +check_integer2(Config) when is_list(Config) -> + ?P(check_integer2), + + ?line ok = verify_int(0, any), + ?line ok = verify_int(-22222, any), + ?line ok = verify_int(33333, any), + ?line ok = verify_int(1, pos), + ?line ok = verify_int(9999, pos), + ?line ok = verify_int(-1, neg), + ?line ok = verify_int(-9999, neg), + ?line ok = verify_int(1, {gt, 0}), + ?line ok = verify_int(88888, {gt, -255}), + ?line ok = verify_int(88888, {gte, -255}), + ?line ok = verify_int(88888, {gte, 88888}), + ?line ok = verify_int(88888, {lt, 88889}), + ?line ok = verify_int(88888, {lte, 88888}), + ?line ok = verify_int(88888, {eq, 88888}), + ?line ok = verify_int(88888, {range, 88887,88889}), + + ?line ok = verify_not_int("kalle & hobbe", any), + ?line ok = verify_not_int(kalle_och_hobbe, any), + ?line ok = verify_not_int(1.5, any), + + ?line ok = verify_not_int(0, pos), + ?line ok = verify_not_int(-22222, pos), + ?line ok = verify_not_int(33333, neg), + ?line ok = verify_not_int(0, {gt, 0}), + ?line ok = verify_not_int(33333, {gt, 99999}), + ?line ok = verify_not_int(33333, {gt, 33333}), + ?line ok = verify_not_int(33333, {gte, 33334}), + ?line ok = verify_not_int(33333, {lt, 33333}), + ?line ok = verify_not_int(33333, {lte, 33332}), + ?line ok = verify_not_int(33333, {eq, 33332}), + ?line ok = verify_not_int(33333, {eq, -33333}), + ?line ok = verify_not_int(33333, {range, 33334, 33338}), + ?line ok = verify_not_int(33339, {range, 33334, 33338}), + ?line ok = verify_not_int(33333, {gt, kalle}), + ?line ok = verify_not_int(33333, {gt, 1.55}), + ?line ok = verify_not_int(33333, {gte, "hejsan"}), + ?line ok = verify_not_int(33333, {lt, hobbe}), + ?line ok = verify_not_int(33333, {lte, 1.7666}), + ?line ok = verify_not_int(33333, {eq, 33333.0}), + ?line ok = verify_not_int(33333, {eq, -33333.0}), + ?line ok = verify_not_int(33333, {range, kalle, 33338}), + ?line ok = verify_not_int(33339, {range, 33334, kalle}), + ?line ok = verify_not_int(33339, {kalle, 33334, kalle}), + + ok. + +verify_int(Val, Cond) -> + case (catch snmp_conf:check_integer(Val, Cond)) of + {error, Reason} -> + ?FAIL({verify_int, Val, Cond, Reason}); + ok -> + ok + end. + +verify_not_int(Val, Cond) -> + case (catch snmp_conf:check_integer(Val, Cond)) of + ok -> + ?FAIL({verify_int, Val, Cond}); + {error, _Reason} -> + ok + end. + +%%====================================================================== + +check_string1(suite) -> []; +check_string1(Config) when is_list(Config) -> + ?P(check_string1), + ?line ok = verify_string("kalle & hobbe"), + ?line ok = verify_not_string(kalle_hobbe), + ?line ok = verify_not_string(1000), + ?line ok = verify_not_string(1.0), + ok. + +verify_string(Val) -> + case (catch snmp_conf:check_string(Val)) of + {error, Reason} -> + ?FAIL({verify_string, Val, Reason}); + ok -> + ok + end. + +verify_not_string(Val) -> + case (catch snmp_conf:check_string(Val)) of + ok -> + ?FAIL({verify_string, Val}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +check_string2(suite) -> []; +check_string2(Config) when is_list(Config) -> + ?P(check_string2), + Str = "kalle & hobbe", + ?line ok = verify_string(Str, any), + ?line ok = verify_string(Str, {gt, length(Str) - 1}), + ?line ok = verify_string(Str, {gte, length(Str)}), + ?line ok = verify_string(Str, {lt, length(Str) + 1}), + ?line ok = verify_string(Str, {lte, length(Str)}), + ?line ok = verify_string(Str, length(Str)), + + ?line ok = verify_not_string(kalle_hobbe, any), + ?line ok = verify_not_string(1000, any), + ?line ok = verify_not_string(1.0, any), + ?line ok = verify_not_string(Str, {gt, length(Str)}), + ?line ok = verify_not_string(Str, {gte, length(Str) + 1}), + ?line ok = verify_not_string(Str, {lt, length(Str)}), + ?line ok = verify_not_string(Str, {lte, length(Str) - 1}), + ?line ok = verify_not_string(Str, length(Str) + 1), + ok. + +verify_string(Val, Limit) -> + case (catch snmp_conf:check_string(Val, Limit)) of + {error, Reason} -> + ?FAIL({verify_string, Val, Limit, Reason}); + ok -> + ok + end. + +verify_not_string(Val, Limit) -> + case (catch snmp_conf:check_string(Val, Limit)) of + ok -> + ?FAIL({verify_string, Val, Limit}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +check_atom(suite) -> []; +check_atom(Config) when is_list(Config) -> + ?P(check_atom), + Atoms = [{kalle, "kalle"}, {hobbe, "hobbe"}, {dummy, "dummy"}], + ?line ok = verify_atom(kalle, Atoms), + ?line ok = verify_not_atom(anka, Atoms), + ?line ok = verify_not_atom("kalle", Atoms), + ?line ok = verify_not_atom(1000, Atoms), + ok. + +verify_atom(Val, Atoms) -> + case (catch snmp_conf:check_atom(Val, Atoms)) of + {error, Reason} -> + ?FAIL({verify_atom, Val, Atoms, Reason}); + {ok, _} -> + ok + end. + +verify_not_atom(Val, Atoms) -> + case (catch snmp_conf:check_atom(Val, Atoms)) of + ok -> + ?FAIL({verify_atom, Val, Atoms}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +check_ip(suite) -> []; +check_ip(Config) when is_list(Config) -> + ?P(check_ip), + ?line ok = verify_ip([1,2,3,4]), + ?line ok = verify_not_ip([1,2,3]), + ?line ok = verify_not_ip([1,2,3,4,5]), + ?line ok = verify_not_ip(kalle), + ?line ok = verify_not_ip(1000), + ?line ok = verify_not_ip([1,2,3.0,4]), + ?line ok = verify_not_ip([1,two,3,4]), + ok. + +verify_ip(Val) -> + case (catch snmp_conf:check_ip(Val)) of + {error, Reason} -> + ?FAIL({verify_ip, Val, Reason}); + ok -> + ok + end. + +verify_not_ip(Val) -> + case (catch snmp_conf:check_ip(Val)) of + ok -> + ?FAIL({verify_ip, Val}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +check_taddress(suite) -> []; +check_taddress(Config) when is_list(Config) -> + ?P(check_taddress), + ?line ok = verify_taddress([1,2,3,4,5,6]), + ?line ok = verify_not_taddress([1,2,3,4,5]), + ?line ok = verify_not_taddress([1,2,3,4,5,6,7]), + ?line ok = verify_not_taddress(kalle), + ?line ok = verify_not_taddress(1000), + ?line ok = verify_not_taddress([1,2,3.0,4,5,6]), + ?line ok = verify_not_taddress([1,two,3,4,5,6]), + ok. + +verify_taddress(Val) -> + case (catch snmp_conf:check_taddress(Val)) of + {error, Reason} -> + ?FAIL({verify_taddress, Val, Reason}); + ok -> + ok + end. + +verify_not_taddress(Val) -> + case (catch snmp_conf:check_taddress(Val)) of + ok -> + ?FAIL({verify_taddress, Val}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +check_packet_size(suite) -> []; +check_packet_size(Config) when is_list(Config) -> + ?P(check_packet_size), + Min = 484, + Max = 2147483647, + ?line ok = verify_packet_size(Min), + ?line ok = verify_packet_size(2*Min), + ?line ok = verify_packet_size(Max), + ?line ok = verify_not_packet_size(Min-1), + ?line ok = verify_not_packet_size(Max+1), + ?line ok = verify_not_packet_size(kalle), + ?line ok = verify_not_packet_size("kalle"), + ?line ok = verify_not_packet_size(1.0), + ?line ok = verify_not_packet_size(1.0*Max), + ok. + +verify_packet_size(Val) -> + case (catch snmp_conf:check_packet_size(Val)) of + {error, Reason} -> + ?FAIL({verify_packet_size, Val, Reason}); + ok -> + ok + end. + +verify_not_packet_size(Val) -> + case (catch snmp_conf:check_packet_size(Val)) of + ok -> + ?FAIL({verify_packet_size, Val}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +check_oid(suite) -> []; +check_oid(Config) when is_list(Config) -> + ?P(check_oid), + [_,_|Rest] = ?otpSnmpeaModule, + ErrOid = [6,16|Rest], + ?line ok = verify_oid(?system), + ?line ok = verify_oid(?sysDescr_instance), + ?line ok = verify_oid(?otpSnmpeaModule), + ?line ok = verify_not_oid(kalle), + ?line ok = verify_not_oid("kalle"), + ?line ok = verify_not_oid(1000), + ?line ok = verify_not_oid(1.0), + ?line ok = verify_not_oid(ErrOid), + ok. + +verify_oid(Val) -> + case (catch snmp_conf:check_oid(Val)) of + {error, Reason} -> + ?FAIL({verify_oid, Val, Reason}); + ok -> + ok + end. + +verify_not_oid(Val) -> + case (catch snmp_conf:check_oid(Val)) of + ok -> + ?FAIL({verify_oid, Val}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +check_sec_model1(suite) -> []; +check_sec_model1(Config) when is_list(Config) -> + ?P(check_sec_model1), + Exclude1 = [], + Exclude2 = [v1], + Exclude3 = [v1,usm], + ?line ok = verify_sec_model(any, Exclude1), + ?line ok = verify_sec_model(v1, Exclude1), + ?line ok = verify_sec_model(v2c, Exclude1), + ?line ok = verify_sec_model(usm, Exclude1), + ?line ok = verify_sec_model(any, Exclude2), + ?line ok = verify_sec_model(v2c, Exclude2), + ?line ok = verify_not_sec_model(v1, Exclude2), + ?line ok = verify_not_sec_model(v1, Exclude3), + ?line ok = verify_not_sec_model(usm, Exclude3), + ok. + +verify_sec_model(Val, Exclude) -> + case (catch snmp_conf:check_sec_model(Val, Exclude)) of + {error, Reason} -> + ?FAIL({verify_sec_model, Val, Reason}); + {ok, _} -> + ok + end. + +verify_not_sec_model(Val, Exclude) -> + case (catch snmp_conf:check_sec_model(Val, Exclude)) of + {ok, Res} -> + ?FAIL({verify_sec_model, Val, Res}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +check_sec_model2(suite) -> []; +check_sec_model2(Config) when is_list(Config) -> + ?P(check_sec_model2), + ?line ok = verify_sec_model(v1, v1, []), + ?line ok = verify_sec_model(v1, v1, [v2c]), + ?line ok = verify_sec_model(v2c, v2c, []), + ?line ok = verify_sec_model(v2c, v2c, [v1]), + ?line ok = verify_sec_model(v3, usm, []), + ?line ok = verify_sec_model(v3, usm, [v2c]), + ?line ok = verify_not_sec_model(v1, v2c, []), + ?line ok = verify_not_sec_model(v1, v3, [v2c]), + ?line ok = verify_not_sec_model(v1, v1, [v1]), + ?line ok = verify_not_sec_model(v2c, v1, []), + ?line ok = verify_not_sec_model(v2c, v3, [v3]), + ?line ok = verify_not_sec_model(v2c, v2c, [v2c]), + ?line ok = verify_not_sec_model(v3, v1, []), + ?line ok = verify_not_sec_model(v3, v2c, [v1]), + ?line ok = verify_not_sec_model(v3, v3, [v2c]), + ?line ok = verify_not_sec_model(kalle, v3, []), + ?line ok = verify_not_sec_model(1000, v3, []), + ?line ok = verify_not_sec_model(1.0, v3, []), + ok. + + +verify_sec_model(M1, M2, Exclude) -> + case (catch snmp_conf:check_sec_model(M1, M2, Exclude)) of + {error, Reason} -> + ?FAIL({verify_sec_model, M1, M2, Reason}); + {ok, _} -> + ok + end. + +verify_not_sec_model(M1, M2, Exclude) -> + case (catch snmp_conf:check_sec_model(M1, M2, Exclude)) of + {ok, Res} -> + ?FAIL({verify_sec_model, M1, M2, Res}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +check_sec_level(suite) -> []; +check_sec_level(Config) when is_list(Config) -> + ?P(check_sec_level), + ?line ok = verify_sec_level(noAuthNoPriv), + ?line ok = verify_sec_level(authNoPriv), + ?line ok = verify_sec_level(authPriv), + ?line ok = verify_not_sec_level(kalle), + ?line ok = verify_not_sec_level("noAuthNoPriv"), + ?line ok = verify_not_sec_level(1000), + ?line ok = verify_not_sec_level(1.0), + ok. + + +verify_sec_level(Val) -> + case (catch snmp_conf:check_sec_level(Val)) of + {error, Reason} -> + ?FAIL({verify_sec_level, Val, Reason}); + {ok, _} -> + ok; + Error -> + ?FAIL({verify_sec_level, Val, Error}) + end. + +verify_not_sec_level(Val) -> + case (catch snmp_conf:check_sec_level(Val)) of + {ok, Res} -> + ?FAIL({verify_sec_level, Val, Res}); + {error, _Reason} -> + ok; + {'EXIT', _Reason} -> + ok + end. + + +%%====================================================================== + +check_timer(suite) -> []; +check_timer(Config) when is_list(Config) -> + ?P(check_timer), + ?line ok = verify_timer(infinity), + ?line ok = verify_timer(1), + ?line ok = verify_timer(10), + ?line ok = verify_timer(2147483647), + ?line ok = verify_timer(2*2147483647), + ?line ok = verify_timer({1,1,0,0}), + ?line ok = verify_timer({10,10,10,10}), + ?line ok = verify_timer({2147483647,2147483647,2147483647,2147483647}), + ?line ok = verify_not_timer(ytinifni), + ?line ok = verify_not_timer("ytinifni"), + ?line ok = verify_not_timer(0), + ?line ok = verify_not_timer(-10), + ?line ok = verify_not_timer({0,1,0,0}), + ?line ok = verify_not_timer({1,0,0,0}), + ?line ok = verify_not_timer({1,1,-1,0}), + ?line ok = verify_not_timer({1,1,0,-1}), + ?line ok = verify_not_timer({1.0,1,0,0}), + ?line ok = verify_not_timer({1,1.0,0,0}), + ?line ok = verify_not_timer({1,1,1.0,0}), + ?line ok = verify_not_timer({1,1,0,1.0}), + ?line ok = verify_not_timer({"1",1,0,0}), + ?line ok = verify_not_timer({1,"1",0,0}), + ?line ok = verify_not_timer({1,1,"0",0}), + ?line ok = verify_not_timer({1,1,0,"0"}), + ok. + +verify_timer(Val) -> + case (catch snmp_conf:check_timer(Val)) of + {error, Reason} -> + ?FAIL({verify_timer, Val, Reason}); + {ok, _} -> + ok + end. + +verify_not_timer(Val) -> + case (catch snmp_conf:check_timer(Val)) of + {ok, Res} -> + ?FAIL({verify_timer, Val, Res}); + {error, _Reason} -> + ok + end. + + +%%====================================================================== + +read(suite) -> []; +read(Config) when is_list(Config) -> + ?P(read), + ?SKIP(not_implemented_yet). + + +%%====================================================================== + +read_files(suite) -> []; +read_files(Config) when is_list(Config) -> + ?P(read_files), + ?SKIP(not_implemented_yet). + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +% d(F) -> +% d(F, []). + +% d(F, A) -> +% io:format("~w:" ++ F ++ "~n", [?MODULE|A]). diff --git a/lib/snmp/test/snmp_log_test.erl b/lib/snmp/test/snmp_log_test.erl new file mode 100644 index 0000000000..b4694fd9ab --- /dev/null +++ b/lib/snmp/test/snmp_log_test.erl @@ -0,0 +1,941 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: +%% +%% Test: ts:run(snmp, snmp_log_test, [batch]). +%% Test: ts:run(snmp, snmp_log_test, log_to_txt2, [batch]). +%% +%%---------------------------------------------------------------------- +-module(snmp_log_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). +-include_lib("kernel/include/file.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + init_per_testcase/2, fin_per_testcase/2, + + all/1, + open_and_close/1, + open_write_and_close/1, + log_to_io1/1, + log_to_io2/1, + log_to_txt1/1, + log_to_txt2/1 + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + log_writer_main/5, + log_reader_main/1 + ]). + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(Case, Config) when is_list(Config) -> + Dir = ?config(priv_dir, Config), + LogTestDir = join(Dir, ?MODULE), + CaseDir = join(LogTestDir, Case), + case file:make_dir(LogTestDir) of + ok -> + ok; + {error, eexist} -> + ok; + Error -> + ?FAIL({failed_creating_subsuite_top_dir, Error}) + end, + ?line ok = file:make_dir(CaseDir), + Dog = ?WD_START(?MINS(5)), + [{log_dir, CaseDir}, {watchdog, Dog}|Config]. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + %% Leave the dirs created above (enable debugging of the test case(s)) + Dog = ?config(watchdog, Config), + ?WD_STOP(Dog), + lists:keydelete(watchdog, 1, Config). + + +%%====================================================================== +%% Test case definitions +%%====================================================================== +%% ?SKIP(not_yet_implemented). +all(suite) -> + [ + open_and_close, + open_write_and_close, + log_to_io1, + log_to_io2, + log_to_txt1, + log_to_txt2 + ]. + + +%%====================================================================== +%% Test functions +%%====================================================================== + +open_and_close(suite) -> []; +open_and_close(Config) when is_list(Config) -> + p(open_and_close), + put(sname,open_and_close), + put(verbosity,trace), + Dir = ?config(log_dir, Config), + Name = "snmp_test", + File = join(Dir, "snmp_test.log"), + Size = {1024, 10}, + Repair = true, + ?line {ok, Log} = snmp_log:create(Name, File, Size, Repair), + ?line ok = snmp_log:sync(Log), + ?line {ok, Info} = snmp_log:info(Log), + display_info(Info), + ?line ok = snmp_log:close(Log). + + +%%====================================================================== + +open_write_and_close(suite) -> []; +open_write_and_close(Config) when is_list(Config) -> + p(open_write_and_close), + put(sname,open_write_and_close), + put(verbosity,trace), + ?DBG("open_write_and_close -> start", []), + Dir = ?config(log_dir, Config), + Name = "snmp_test", + File = join(Dir, "snmp_test.log"), + Size = {1024, 10}, + Repair = true, + ?DBG("open_write_and_close -> create log", []), + ?line {ok, Log} = snmp_log:create(Name, File, Size, Repair), + + Vsn = 'version-2', + Community = "all-rights", + + ?DBG("open_write_and_close -> create messages to log", []), + %% A request + ?line Req = get_next_request(Vsn, Community, [1,1], 1, 235779012), + + %% A reply + ?line Rep = get_response(Vsn, Community, + [1,3,6,1,2,1,1,1,0], 'OCTET STRING', + "Erlang SNMP agent", 1, 235779012), + + %% Create a list of messages to log: + Msgs = lists:flatten(lists:duplicate(1002,[Req,Rep])), + + %% And now log them: + ?DBG("open_write_and_close -> log ~p messages, ~p bytes", + [length(Msgs), size(list_to_binary(Msgs))]), + Addr = ?LOCALHOST(), + Port = 162, + Logger = fun(Packet) -> + ?line ok = snmp_log:log(Log, Packet, Addr, Port) + end, + lists:foreach(Logger, Msgs), + check_notify(), + + ?DBG("open_write_and_close -> display info", []), + ?line {ok, Info} = snmp_log:info(Log), + display_info(Info), + + ?DBG("open_write_and_close -> close log", []), + ?line ok = snmp_log:close(Log), + + ?DBG("open_write_and_close -> done", []), + ok. + + + +%%====================================================================== + +log_to_io1(suite) -> []; +log_to_io1(doc) -> "Log to io from the same process that opened " + "and wrote the log"; +log_to_io1(Config) when is_list(Config) -> + p(log_to_io1), + put(sname,l2i1), + put(verbosity,trace), + ?DBG("log_to_io1 -> start", []), + Dir = ?config(log_dir, Config), + Name = "snmp_test_l2i1", + File = join(Dir, "snmp_test_l2i1.log"), + Size = {1024, 10}, + Repair = true, + ?DBG("log_to_io1 -> create log", []), + ?line {ok, Log} = snmp_log:create(Name, File, Size, Repair), + + ?DBG("log_to_io1 -> create messages to log", []), + Msgs = messages(), + + ?DBG("log_to_io1 -> create logger funs", []), + Addr = ?LOCALHOST(), + Port = 162, + Logger = fun(Packet) -> + ?line ok = snmp_log:log(Log, Packet, Addr, Port) + end, + BatchLogger = fun(Time) -> + lists:foreach(Logger, Msgs), + ?SLEEP(Time), + ok + end, + To = lists:duplicate(100, 100), + + ?DBG("log_to_io1 -> log the messages", []), + lists:foreach(BatchLogger, To), + + ?DBG("log_to_io1 -> display info", []), + ?line {ok, Info} = snmp_log:info(Log), + display_info(Info), + + ?DBG("log_to_io1 -> do the convert to io (stdout)", []), + ? line ok = snmp_log:log_to_io(Log, File, Dir, []), + + ?DBG("log_to_io1 -> close log", []), + ?line ok = snmp_log:close(Log), + + ?DBG("log_to_io1 -> done", []), + ok. + + +%%====================================================================== +%% Starta en logger-process som med ett visst intervall loggar +%% meddelanden. Starta en reader-process som vid ett viss tillf�lle +%% l�ser fr�n loggen. + +log_to_io2(suite) -> []; +log_to_io2(doc) -> "Log to io from a different process than which " + "opened and wrote the log"; +log_to_io2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + p(log_to_io2), + put(sname, l2i2), + put(verbosity,trace), + ?DBG("log_to_io2 -> start", []), + Dir = ?config(log_dir, Config), + Name = "snmp_test_l2i2", + File = join(Dir, "snmp_test_l2i2.log"), + Size = {1024, 10}, + Repair = true, + + ?DBG("log_to_io2 -> create log writer process", []), + ?line {ok, Log, Logger} = log_writer_start(Name, File, Size, Repair), + + ?DBG("log_to_io2 -> create log reader process", []), + ?line {ok, Reader} = log_reader_start(), + + ?DBG("log_to_io2 -> wait some time", []), + ?SLEEP(5000), + + ?DBG("log_to_io2 -> display log info", []), + ?line log_writer_info(Logger), + + ?DBG("log_to_io2 -> instruct the log writer to sleep some", []), + ?line ok = log_writer_sleep(Logger, 5000), + + ?DBG("log_to_io2 -> instruct the log reader to log to io", []), + Res = + log_reader_log_to(Reader, + fun() -> + I = disk_log:info(Log), + R = snmp_log:log_to_io(Log, File, Dir, []), + {R, I} + end), + + case Res of + {ok, Info} -> + ?DBG("log_to_io2 -> ~n Info: ~p", [Info]), + ok; + {Error, Info} -> + ?DBG("log_to_io2 -> log to io failed: " + "~n Error: ~p" + "~n Info: ~p", [Error, Info]), + ?line ?FAIL({log_lo_io_failed, Error, Info}) + end, + + ?DBG("log_to_io2 -> instruct the log writer to stop", []), + ?line log_writer_stop(Logger), + + ?DBG("log_to_io2 -> instruct the log reader to stop", []), + ?line log_reader_stop(Reader), + + ?DBG("log_to_io2 -> done", []), + ok. + + +%%====================================================================== + +log_to_txt1(suite) -> []; +log_to_txt1(Config) when is_list(Config) -> + p(log_to_txt1), + put(sname,l2t1), + put(verbosity,trace), + ?DBG("log_to_txt1 -> start", []), + Dir = ?config(log_dir, Config), + Name = "snmp_test_l2t1", + File = join(Dir, "snmp_test_l2t1.log"), + Size = {10240, 10}, + Repair = true, + ?DBG("log_to_txt1 -> create log", []), + ?line {ok, Log} = snmp_log:create(Name, File, Size, Repair), + + ?DBG("log_to_txt1 -> create messages to log", []), + Msgs = messages(), + + ?DBG("log_to_txt1 -> create logger funs", []), + Addr = ?LOCALHOST(), + Port = 162, + Logger = fun(Packet) -> + ?line ok = snmp_log:log(Log, Packet, Addr, Port) + end, + BatchLogger = fun(Time) -> + lists:foreach(Logger, Msgs), + ?SLEEP(Time), + ok + end, + To = lists:duplicate(20, 5000), + + ?DBG("log_to_txt1 -> log the messages", []), + Start = calendar:local_time(), + lists:foreach(BatchLogger, To), + Stop = calendar:local_time(), + + ?DBG("log_to_txt1 -> display info", []), + ?line {ok, Info} = snmp_log:info(Log), + display_info(Info), + + Out1 = join(Dir, "snmp_text-1.txt"), + ?DBG("log_to_txt1 -> do the convert to a text file when" + "~n Out1: ~p", [Out1]), + ?line ok = snmp:log_to_txt(Dir, [], Out1, Log, File), + + ?line {ok, #file_info{size = Size1}} = file:read_file_info(Out1), + ?DBG("log_to_txt1 -> text file size: ~p", [Size1]), + validate_size(Size1), + + Out2 = join(Dir, "snmp_text-2.txt"), + ?DBG("log_to_txt1 -> do the convert to a text file when" + "~n Start: ~p" + "~n Stop: ~p" + "~n Out2: ~p", [Start, Stop, Out2]), + ?line ok = snmp:log_to_txt(Dir, [], Out2, Log, File, Start, Stop), + + ?line {ok, #file_info{size = Size2}} = file:read_file_info(Out2), + ?DBG("log_to_txt1 -> text file size: ~p", [Size2]), + validate_size(Size2, {le, Size1}), + + %% Calculate new start / stop times... + GStart = calendar:datetime_to_gregorian_seconds(Start), + ?DBG("log_to_txt1 -> GStart: ~p", [GStart]), + GStop = calendar:datetime_to_gregorian_seconds(Stop), + ?DBG("log_to_txt1 -> GStop: ~p", [GStop]), + Diff4 = (GStop - GStart) div 4, + ?DBG("log_to_txt1 -> Diff4: ~p", [Diff4]), + GStart2 = GStart + Diff4, + GStop2 = GStop - Diff4, + if + GStop2 > GStart2 -> + ok; + true -> + ?FAIL({date_calc_failure, GStart2, GStop2}) + end, + + Start2 = calendar:gregorian_seconds_to_datetime(GStart2), + Stop2 = calendar:gregorian_seconds_to_datetime(GStop2), + + Out3 = join(Dir, "snmp_text-3.txt"), + ?DBG("log_to_txt1 -> do the convert to a text file when" + "~n Start2: ~p" + "~n Stop2: ~p" + "~n Out3: ~p", [Start2, Stop2, Out3]), + ?line ok = snmp:log_to_txt(Dir, [], Out3, Log, File, Start2, Stop2), + + ?line {ok, #file_info{size = Size3}} = file:read_file_info(Out3), + ?DBG("log_to_txt1 -> text file size: ~p", [Size3]), + validate_size(Size3, {l, Size1}), + + ?DBG("log_to_txt1 -> close log", []), + ?line ok = snmp_log:close(Log), + + ?DBG("log_to_txt1 -> done", []), + ok. + + +%%====================================================================== +%% Starta en logger-process som med ett visst intervall loggar +%% meddelanden. Starta en reader-process som vid ett viss tillf�lle +%% l�ser fr�n loggen. +%% +%% Test: ts:run(snmp, snmp_log_test, log_to_txt2, [batch]). + +log_to_txt2(suite) -> []; +log_to_txt2(doc) -> "Log to txt file from a different process than which " + "opened and wrote the log"; +log_to_txt2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + p(log_to_txt2), + put(sname,l2t2), + put(verbosity,trace), + ?DBG("log_to_txt2 -> start", []), + Dir = ?config(log_dir, Config), + Name = "snmp_test_l2t2", + LogFile = join(Dir, "snmp_test_l2t2.log"), + TxtFile = join(Dir, "snmp_test_l2t2.txt"), + Meg = 1024*1024, + Size = {10*Meg, 10}, + Repair = true, + + StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + Mibs = [join(StdMibDir, "SNMPv2-MIB")], + + ?DBG("log_to_txt2 -> create log writer process", []), + ?line {ok, Log, Logger} = log_writer_start(Name, LogFile, Size, Repair), + + ?DBG("log_to_txt2 -> create log reader process", []), + ?line {ok, Reader} = log_reader_start(), + + ?DBG("log_to_txt2 -> wait some time", []), + ?SLEEP(5000), + + ?DBG("log_to_txt2 -> display log info", []), + ?line log_writer_info(Logger), + + ?DBG("log_to_txt2 -> instruct the log writer to sleep some", []), + ?line ok = log_writer_sleep(Logger, 5000), + + ?DBG("log_to_txt2 -> instruct the log reader to log to txt", []), + Res = + log_reader_log_to(Reader, + fun() -> + I = disk_log:info(Log), + T1 = t(), + R = snmp_log:log_to_txt(Log, LogFile, Dir, + Mibs, TxtFile), + T2 = t(), + io:format(user, + "Time converting file: ~w ms~n", + [T2 - T1]), + {R, I} + end), + + case Res of + {ok, Info} -> + ?DBG("log_to_txt2 -> ~n Info: ~p", [Info]), + ?line {ok, #file_info{size = FileSize}} = + file:read_file_info(TxtFile), + ?DBG("log_to_txt2 -> text file size: ~p", [FileSize]), + validate_size(FileSize); + {Error, Info} -> + ?DBG("log_to_txt2 -> log to txt failed: " + "~n Error: ~p" + "~n Info: ~p", [Error, Info]), + ?line ?FAIL({log_lo_txt_failed, Error, Info}) + end, + + ?DBG("log_to_txt2 -> instruct the log writer to stop", []), + ?line log_writer_stop(Logger), + + ?DBG("log_to_txt2 -> instruct the log reader to stop", []), + ?line log_reader_stop(Reader), + + ?DBG("log_to_txt2 -> done", []), + ok. + + +validate_size(0) -> + ?FAIL(invalid_size); +validate_size(_) -> + ok. + +validate_size(0, _) -> + ?FAIL(invalid_size); +validate_size(A, {le, B}) when A =< B -> + ok; +validate_size(A, {l, B}) when A < B -> + ok; +validate_size(A, B) -> + ?FAIL({invalid_size, A, B}). + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +log_writer_start(Name, File, Size, Repair) -> + Pid = spawn_link(?MODULE, log_writer_main, + [Name, File, Size, Repair, self()]), + receive + {log, Log, Pid} -> + {ok, Log, Pid}; + {'EXIT', Pid, Reason} -> + {error, Reason} + after 60000 -> + Msg = receive Any -> Any after 0 -> nothing end, + Info = (catch process_info(Pid)), + exit({failed_starting_writer, timeout, Msg, Info}) + end. + +log_writer_stop(Pid) -> + Pid ! {stop, self()}, + T1 = t(), + receive + {'EXIT', Pid, normal} -> + T2 = t(), + ?DBG("it took ~w ms to stop the writer", [T2 - T1]), + ok + after 60000 -> + Msg = receive Any -> Any after 0 -> nothing end, + Info = (catch process_info(Pid)), + exit({failed_stopping_writer, timeout, Msg, Info}) + end. + +log_writer_info(Pid) -> + Pid ! {info, self()}. + +log_writer_sleep(Pid, Time) -> + Pid ! {sleep, Time, self()}, + T1 = t(), + receive + {sleeping, Pid} -> + T2 = t(), + ?DBG("it took ~w ms to put the writer to sleep", [T2 - T1]), + ok; + {'EXIT', Pid, Reason} -> + {error, Reason} + after 60000 -> + Msg = receive Any -> Any after 0 -> nothing end, + Info = (catch process_info(Pid)), + exit({failed_put_writer_to_sleep, timeout, Msg, Info}) + end. + +log_writer_main(Name, File, Size, Repair, P) -> + process_flag(trap_exit, true), + %% put(sname,log_writer), + %% put(verbosity,trace), + {ok, Log} = snmp_log:create(Name, File, Size, Repair), + P ! {log, Log, self()}, + Msgs = lists:flatten(lists:duplicate(10, messages())), + Addr = ?LOCALHOST(), + Port = 162, + Logger = fun(Packet) -> + ?line ok = snmp_log:log(Log, Packet, Addr, Port) + end, + BatchLogger = fun(Time) -> + lists:foreach(Logger, Msgs), + ?SLEEP(Time), + ok + end, + log_writer(Log, BatchLogger, P). + +log_writer(Log, Fun, P) -> + lp("entry"), + receive + {stop, P} -> + lp("received stop request"), + ok = snmp_log:close(Log), + exit(normal); + {info, P} -> + lp("received info request"), + {ok, Info} = snmp_log:info(Log), + display_info(Info), + log_writer(Log, Fun, P); + {sleep, Time, P} -> + lp("received sleep (~w) request", [Time]), + P ! {sleeping, self()}, + ?SLEEP(Time), + lp("done sleeping"), + log_writer(Log, Fun, P); + ELSE -> + io:format("ERROR:logger - received unknown message: " + "~n ~p~n", [ELSE]), + log_writer(Log, Fun, P) + after 1000 -> + lp("log some messages"), + To = lists:duplicate(100, 100), + lists:foreach(Fun, To), + log_writer(Log, Fun, P) + end. + +lp(F) -> + lp(F, []). + +lp(F, A) -> + io:format(user,"writer [~w] " ++ F ++ "~n", [self()|A]). + +%% -- + +log_reader_start() -> + Pid = spawn_link(?MODULE, log_reader_main, [self()]), + T1 = t(), + receive + {started, Pid} -> + T2 = t(), + ?DBG("it took ~w ms to start the reader", [T2 - T1]), + {ok, Pid}; + {'EXIT', Pid, Reason} -> + {error, Reason} + after 1000 -> + error + end. + +log_reader_stop(Pid) -> + Pid ! {stop, self()}, + T1 = t(), + receive + {'EXIT', Pid, normal} -> + T2 = t(), + ?DBG("it took ~w ms to put the reader to eleep", [T2 - T1]), + ok + after 1000 -> + Msg = receive Any -> Any after 0 -> nothing end, + exit({failed_stopping_reader, timeout, Msg}) + end. + +log_reader_log_to(Pid, LogToFun) when is_function(LogToFun) -> + Pid ! {log_to, LogToFun, self()}, + receive + {log_to_reply, Res, Pid} -> + Res + end. + +log_reader_main(P) -> + put(sname,log_reader), + put(verbosity,trace), + P ! {started, self()}, + log_reader(P). + +log_reader(P) -> + rp("entry"), + receive + {stop, P} -> + rp("received stop request"), + exit(normal); + {log_to, F, P} -> + rp("received log_to request"), + Res = F(), + rp("done with log_to - sending reply"), + P ! {log_to_reply, Res, self()}, + log_reader(P); + ELSE -> + io:format("ERROR:reader - received unknown message: " + "~n ~p~n", [ELSE]), + log_reader(P) + end. + +rp(F) -> + rp(F, []). + +rp(F, A) -> + io:format(user, "reader [~w] " ++ F ++ "~n", [self()|A]). + + +%%====================================================================== + +check_notify() -> + receive + {disk_log, Node, LogName, Info} -> + io:format("disk_log notify: " + "~n Node: ~p" + "~n LogName: ~s" + "~n Info: ~p" + "~n", [Node, LogName, Info]), + check_notify() + after 1000 -> + done + end. + + +messages() -> + [get_next_request('version-1', "all-rights", + [1,13], 1, 1101), + get_response('version-1', "all-rights", + [1,3,6,1,2,1,1,1,0], + 'OCTET STRING', "Erlang SNMP agent", + 1, 1101), + get_request('version-1', "all-rights", + [1,3,6,1,2,1,1,1,0], 1, 1102), + get_response('version-1', "all-rights", + [1,3,6,1,2,1,1,1,0], + 'OCTET STRING', "Erlang SNMP agent", + 1, 1102), + set_request('version-1', "all-rights", + [1,3,6,1,2,1,1,6,0], + 'OCTET STRING', "new_value", + 1, 1003), + get_response('version-1', "all-rights", + [1,3,6,1,2,1,1,6,0], + 'OCTET STRING', "new_value", + 1, 1103), + get_bulk_request("all-rights", 1104), + bulk_get_response('version-1', "all-rights", + [48,29,6,8,43,6,1,2,1,1,1,0,4,17,69,114,108,97, + 110,103,32,83,78,77,80,32,97,103,101,110,116, + 48,7,6,3,43,7,1,130,0], 1104), + inform_request("all-rights", 1105), + get_response('version-1', "all-rights", + [{[1,3,6,1,2,1,1,3,0], + 'TimeTicks', + 4046, + 1}, + {[1,3,6,1,6,3,1,1,4,1,0], + 'OBJECT IDENTIFIER', + [1,3,6,1,2,1,1,0,1],2}], + 1105), + snmpv2_trap("all-rights", 1106), + trap("all-rights")]. + + +get_request(Vsn, Community, Oid, OrgIdx, ReqId) -> + Varbind = #varbind{oid = Oid, + variabletype = 'NULL', + value = 'NULL', + org_index = OrgIdx}, + Pdu = #pdu{type = 'get-response', + request_id = ReqId, + error_status = noError, + error_index = 0, + varbinds = [Varbind]}, + enc_message(Vsn, Community, Pdu). + +get_next_request(Vsn, Community, Oid, OrgIdx, ReqId) -> + Varbind = #varbind{oid = Oid, + variabletype = 'NULL', + value = 'NULL', + org_index = OrgIdx}, + Pdu = #pdu{type = 'get-next-request', + request_id = ReqId, + error_status = noError, + error_index = 0, + varbinds = [Varbind]}, + enc_message(Vsn, Community, Pdu). + +bulk_get_response(Vsn, Community, Bulk, ReqId) -> + Pdu = #pdu{type = 'get-response', + request_id = ReqId, + error_status = noError, + error_index = 0, + varbinds = Bulk}, + enc_message(Vsn, Community, Pdu). + +get_response(Vsn, Community, VarbindData, ReqId) -> + Varbinds = varbinds(VarbindData, []), + Pdu = #pdu{type = 'get-response', + request_id = ReqId, + error_status = noError, + error_index = 0, + varbinds = Varbinds}, + enc_message(Vsn, Community, Pdu). + +get_response(Vsn, Community, Oid, Type, Value, OrgIdx, ReqId) -> + Varbind = #varbind{oid = Oid, + variabletype = Type, + value = Value, + org_index = OrgIdx}, + Pdu = #pdu{type = 'get-response', + request_id = ReqId, + error_status = noError, + error_index = 0, + varbinds = [Varbind]}, + enc_message(Vsn, Community, Pdu). + +set_request(Vsn, Community, Oid, Type, Value, OrgIdx, ReqId) -> + Varbind = #varbind{oid = Oid, + variabletype = Type, + value = Value, + org_index = OrgIdx}, + Pdu = #pdu{type = 'set-request', + request_id = ReqId, + error_status = noError, + error_index = 0, + varbinds = [Varbind]}, + enc_message(Vsn, Community, Pdu). + + +get_bulk_request(Community, ReqId) -> + Varbinds = [#varbind{oid = [1,3,6,1,2,1,1,1], + variabletype = 'NULL', + value = 'NULL', + org_index = 1}, + #varbind{oid = [1,3,7,1], + variabletype = 'NULL', + value = 'NULL', + org_index = 2}], + Pdu = #pdu{type = 'get-bulk-request', + request_id = ReqId, + error_status = 1, + error_index = 1, + varbinds = Varbinds}, + enc_message('version-2', Community, Pdu). + +inform_request(Community, ReqId) -> + Varbinds = [#varbind{oid = [1,3,6,1,2,1,1,3,0], + variabletype = 'TimeTicks', + value = 4046, + org_index = 1}, + #varbind{oid = [1,3,6,1,6,3,1,1,4,1,0], + variabletype = 'OBJECT IDENTIFIER', + value = [1,3,6,1,2,1,1,0,1], + org_index = 2}], + Pdu = #pdu{type = 'inform-request', + request_id = ReqId, + error_status = noError, + error_index = 0, + varbinds = Varbinds}, + enc_message('version-2', Community, Pdu). + +snmpv2_trap(Community, ReqId) -> + Varbinds = [#varbind{oid = [1,3,6,1,2,1,1,3,0], + variabletype = 'TimeTicks', + value = 3945, + org_index = 1}, + #varbind{oid = [1,3,6,1,6,3,1,1,4,1,0], + variabletype = 'OBJECT IDENTIFIER', + value = [1,3,6,1,2,1,11,1], + org_index = 2}], + Pdu = #pdu{type = 'snmpv2-trap', + request_id = ReqId, + error_status = noError, + error_index = 0, + varbinds = Varbinds}, + enc_message('version-2', Community, Pdu). + +% report() -> +% Varbind = #varbind{oid = ?snmpUnknownPDUHandlers, +% variabletype = 'Counter32', +% value = 111}, +% Pdu = #pdu{type = report, +% request_id = 991199, +% error_status = noError, +% error_index = 0, +% varbinds = [Varbind]}, +% enc_message('version-3', Community, Pdu). + +trap(Community) -> + Enterp = [1,3,6,1,2,1,1], + Oid = [1,3,6,1,2,1,1,4,0], + Type = 'OCTET STRING', + Value = "{mbj,eklas}@erlang.ericsson.se", + SysUpTime = 4379, + Spec = 1, + Generic = 6, + AgentIp = [127,0,0,1], + trap(Community, Enterp, Oid, Type, Value, SysUpTime, + Spec, Generic, AgentIp, 1). + +%% V1 trap +trap(Community, Enterp, Oid, Type, Value, SysUpTime, + Spec, Generic, AgentIp, OrgIdx) -> + Varbind = #varbind{oid = Oid, + variabletype = Type, + value = Value, + org_index = OrgIdx}, + Trap = #trappdu{enterprise = Enterp, + agent_addr = AgentIp, + generic_trap = Generic, + specific_trap = Spec, + time_stamp = SysUpTime, + varbinds = [Varbind]}, + enc_message('version-1', Community, Trap). + +varbinds([], Varbinds) -> + lists:reverse(Varbinds); +varbinds([{Oid, Type, Value, Idx}|T], Acc) -> + Varbind = #varbind{oid = Oid, + variabletype = Type, + value = Value, + org_index = Idx}, + varbinds(T, [Varbind|Acc]). + +% enc_message('version-3' = Vsn, Community, Pdu) -> +% ScopedPDU = #scopedPdu{contextEngineID = ContextEngineID, +% contextName = ContextName, +% data = Pdu}, +% NUsmSecParams = +% UsmSecParams#usmSecurityParameters{msgAuthenticationParameters = +% AuthParams}, +% SecBytes = snmp_pdus:enc_usm_security_parameters(NUsmSecParams), +% V3Hdr = #v3_hdr{msgID = MsgID, +% msgMaxSize = AgentMS, +% msgFlags = snmp_misc:mk_msg_flags(Type, SecLevel), +% msgSecurityParameters = SecBytes +% msgSecurityModel = MsgSecurityModel}, +% Msg = #message{version = Vsn, vsn_hdr = V3Hdr, +% data = ScopedPDUBytes}, +% snmp_pdus:enc_message_only(Message2); + +enc_message(Vsn, Community, Pdu) -> + PduBytes = snmp_pdus:enc_pdu(Pdu), + Msg = #message{version = Vsn, + vsn_hdr = Community, + data = PduBytes}, + list_to_binary(snmp_pdus:enc_message_only(Msg)). + +display_info(Info) -> + {SinceOpened, SinceLastInfo} = get_info(no_overflows, Info, {-1,-1}), + CurrentFile = get_info(current_file, Info, -1), + NoItems = get_info(no_current_items, Info, -1), + NoBytes = get_info(no_current_bytes, Info, -1), + io:format(user, "Disk log info: " + "~n Number of filled since opened: ~p" + "~n Number of filled since last info: ~p" + "~n Current file: ~p" + "~n Number of items in file: ~p" + "~n Number of bytes in file: ~p" + "~n", + [SinceOpened, SinceLastInfo, CurrentFile, NoItems, NoBytes]). + +get_info(Key, Info, Def) -> + case lists:keysearch(Key, 1, Info) of + {value, {Key, Val}} -> + Val; + false -> + Def + end. + +join(D, F) -> + filename:join(D, F). + +p(Case) -> + io:format(user, "test case: ~w~n", [Case]). + +%% Time in milli sec +t() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). diff --git a/lib/snmp/test/snmp_manager_config_test.erl b/lib/snmp/test/snmp_manager_config_test.erl new file mode 100644 index 0000000000..51325996e6 --- /dev/null +++ b/lib/snmp/test/snmp_manager_config_test.erl @@ -0,0 +1,2535 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: +%% +%% Test: +%% ts:run(). +%% ts:run(snmp, [batch]). +%% ts:run(snmp, snmp_manager_config_test, [batch]). +%% +%%---------------------------------------------------------------------- +-module(snmp_manager_config_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-include_lib("snmp/src/manager/snmpm_usm.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +%% -compile(export_all). + +-export([ + all/1, + init_per_testcase/2, fin_per_testcase/2, + + start_and_stop/1, + + simple_start_and_stop/1, + start_without_mandatory_opts1/1, + start_without_mandatory_opts2/1, + start_with_all_valid_opts/1, + start_with_unknown_opts/1, + start_with_incorrect_opts/1, + start_with_invalid_manager_conf_file1/1, + start_with_invalid_users_conf_file1/1, + start_with_invalid_agents_conf_file1/1, + start_with_invalid_usm_conf_file1/1, + + normal_op/1, + + system/1, + simple_system_op/1, + + users/1, + register_user_using_file/1, + register_user_using_function/1, + register_user_failed_using_function1/1, + + agents/1, + register_agent_using_file/1, + register_agent_using_function/1, + register_agent_failed_using_function1/1, + + usm_users/1, + register_usm_user_using_file/1, + register_usm_user_using_function/1, + register_usm_user_failed_using_function1/1, + update_usm_user_info/1, + + counter/1, + create_and_increment/1, + + stats_counter/1, + stats_create_and_increment/1, + + tickets/1, + otp_7219/1 + + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + ]). + + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(Case, Config) when is_list(Config) -> + p("init_per_testcase -> Case: ~p", [Case]), + SnmpPrivDir = ?config(priv_dir, Config), + p("init_per_testcase -> SnmpPrivDir: ~p", [SnmpPrivDir]), + SuiteDir = atom_to_list(?MODULE), + SuiteTopDir = filename:join(SnmpPrivDir, SuiteDir), + case file:make_dir(SuiteTopDir) of + ok -> + ok; + {error, eexist} -> + ok; + {error, Reason} -> + ?FAIL({failed_creating, SuiteTopDir, Reason}) + end, + p("init_per_testcase -> SuiteTopDir: ~p", [SuiteTopDir]), + CaseDir = atom_to_list(Case), + ?line ok = + file:make_dir(CaseTopDir = filename:join(SuiteTopDir, CaseDir)), + p("init_per_testcase -> CaseTopDir: ~p", [CaseTopDir]), + ?line ok = + file:make_dir(MgrTopDir = filename:join(CaseTopDir, "manager/")), + ?line ok = + file:make_dir(MgrConfDir = filename:join(MgrTopDir, "conf/")), + ?line ok = + file:make_dir(MgrDbDir = filename:join(MgrTopDir, "db/")), + ?line ok = + file:make_dir(MgrLogDir = filename:join(MgrTopDir, "log/")), + [{case_top_dir, CaseTopDir}, + {manager_dir, MgrTopDir}, + {manager_conf_dir, MgrConfDir}, + {manager_db_dir, MgrDbDir}, + {manager_log_dir, MgrLogDir} | Config]. + + +fin_per_testcase(Case, Config) when is_list(Config) -> + p("fin_per_testcase -> Case: ~p", [Case]), + %% The cleanup is removed due to some really discusting NFS behaviour... + %% CaseTopDir = ?config(manager_dir, Config), + %% ?line ok = ?DEL_DIR(CaseTopDir), + Config. + + +%%====================================================================== +%% Test case definitions +%%====================================================================== +% all(doc) -> +% "The top snmp manager config test case"; +all(suite) -> + [ + start_and_stop, + normal_op, + tickets + ]. + + +%%====================================================================== +%% Test functions +%%====================================================================== + +start_and_stop(doc) -> + "A collection of start and stop tests"; +start_and_stop(suite) -> + [ + simple_start_and_stop, + start_without_mandatory_opts1, + start_without_mandatory_opts2, + start_with_all_valid_opts, + start_with_unknown_opts, + start_with_incorrect_opts, + start_with_invalid_manager_conf_file1, + start_with_invalid_users_conf_file1, + start_with_invalid_agents_conf_file1, + start_with_invalid_usm_conf_file1 + ]. + + +%% +%% --- +%% + +simple_start_and_stop(suite) -> []; +simple_start_and_stop(doc) -> + "Start the snmp manager config process with the \n" + "minimum setof options (config dir)."; +simple_start_and_stop(Conf) when is_list(Conf) -> + put(tname,ssas), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{versions, [v1]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + ?line {ok, _Pid} = snmpm_config:start_link(Opts), + ?line ok = snmpm_config:stop(), + + ok. + + +%% +%% --- +%% + +start_without_mandatory_opts1(suite) -> []; +start_without_mandatory_opts1(doc) -> + "Start the snmp manager config process with some of the \n" + "mandatory options missing."; +start_without_mandatory_opts1(Conf) when is_list(Conf) -> + put(tname,swomo1), + put(verbosity,trace), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + + %% config, but no dir: + p("config option, but no dir"), + Opts = [{priority, normal}, + {config, [{verbosity, trace}, {db_dir, DbDir}]}, {mibs, []}], + ?line {error, {missing_mandatory,dir}} = config_start(Opts), + + p("done"), + ok. + + +%% +%% --- +%% + +start_without_mandatory_opts2(suite) -> []; +start_without_mandatory_opts2(doc) -> + "Start the snmp manager config process with some of the \n" + "mandatory options missing."; +start_without_mandatory_opts2(Conf) when is_list(Conf) -> + put(tname,swomo2), + put(verbosity,trace), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + + write_manager_conf(ConfDir), + + + %% Second set of options (no config): + p("no config option"), + Opts = [{priority, normal}, + {mibs, []}], + ?line {error, {missing_mandatory,config,[dir, db_dir]}} = + config_start(Opts), + + p("done"), + ok. + + +%% +%% --- +%% + +start_with_all_valid_opts(suite) -> []; +start_with_all_valid_opts(doc) -> + "Start the snmp manager config process with the \n" + "complete set of all the valid options."; +start_with_all_valid_opts(Conf) when is_list(Conf) -> + put(tname,swavo), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + LogDir = ?config(manager_log_dir, Conf), + StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + + write_manager_conf(ConfDir), + + + %% Third set of options (no versions): + p("all options"), + NetIfOpts = [{module, snmpm_net_if}, + {verbosity, trace}, + {options, [{recbuf, 30000}, + {bind_to, false}, + {no_reuse, false}]}], + ServerOpts = [{timeout, 10000}, {verbosity, trace}], + NoteStoreOpts = [{timeout, 20000}, {verbosity, trace}], + ConfigOpts = [{dir, ConfDir}, {verbosity, trace}, {db_dir, DbDir}], + Mibs = [join(StdMibDir, "SNMP-NOTIFICATION-MIB"), + join(StdMibDir, "SNMP-USER-BASED-SM-MIB")], + Prio = normal, + ATL = [{type, read_write}, + {dir, LogDir}, + {size, {10,10240}}, + {repair, true}], + Vsns = [v1,v2,v3], + Opts = [{config, ConfigOpts}, + {net_if, NetIfOpts}, + {server, ServerOpts}, + {note_store, NoteStoreOpts}, + {audit_trail_log, ATL}, + {priority, Prio}, + {mibs, Mibs}, + {versions, Vsns}], + ?line {ok, _Pid} = config_start(Opts), + ?line ok = config_stop(), + + p("done"), + ok. + + +%% +%% --- +%% + +start_with_unknown_opts(suite) -> []; +start_with_unknown_opts(doc) -> + "Start the snmp manager config process when some of\n" + "the options are unknown."; +start_with_unknown_opts(Conf) when is_list(Conf) -> + put(tname,swuo), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + LogDir = ?config(manager_log_dir, Conf), + StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + + write_manager_conf(ConfDir), + + + %% Third set of options (no versions): + p("all options"), + NetIfOpts = [{module, snmpm_net_if}, + {verbosity, trace}, + {options, [{recbuf, 30000}, + {bind_to, false}, + {no_reuse, false}]}], + ServerOpts = [{timeout, 10000}, {verbosity, trace}], + NoteStoreOpts = [{timeout, 20000}, {verbosity, trace}], + ConfigOpts = [{dir, ConfDir}, {verbosity, trace}, {db_dir, DbDir}], + Mibs = [join(StdMibDir, "SNMP-NOTIFICATION-MIB"), + join(StdMibDir, "SNMP-USER-BASED-SM-MIB")], + Prio = normal, + ATL = [{type, read_write}, + {dir, LogDir}, + {size, {10,10240}}, + {repair, true}], + Vsns = [v1,v2,v3], + Opts = [{config, ConfigOpts}, + {net_if, NetIfOpts}, + {server, ServerOpts}, + {note_store, NoteStoreOpts}, + {audit_trail_log, ATL}, + {unknown_option, "dummy value"}, + {priority, Prio}, + {mibs, Mibs}, + {versions, Vsns}], + ?line {ok, _Pid} = config_start(Opts), + + p("done"), + ok. + + +%% +%% --- +%% + +start_with_incorrect_opts(suite) -> []; +start_with_incorrect_opts(doc) -> + "Start the snmp manager config process when some of\n" + "the options has incorrect values."; +start_with_incorrect_opts(Conf) when is_list(Conf) -> + put(tname,swio), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + LogDir = ?config(manager_log_dir, Conf), + StdMibDir = filename:join(code:priv_dir(snmp), "mibs") ++ "/", + + write_manager_conf(ConfDir), + + ConfigOpts = [{verbosity,trace}, {dir, ConfDir}, {db_dir, DbDir}], + + p("net-if - incorrect module"), + NetIfOpts1 = [{module, snmpm_user}], %% Behaviour check will fail + Opts01 = [{config, ConfigOpts}, {versions, [v1]}, + {net_if, NetIfOpts1}], + ?line {error, Reason01} = config_start(Opts01), + p("net-if (module) res: ~p", [Reason01]), + + p("net-if - incorrect verbosity"), + NetIfOpts2 = [{verbosity, invalid_verbosity}], + Opts02 = [{config, ConfigOpts}, {versions, [v1]}, + {net_if, NetIfOpts2}], + ?line {error, Reason02} = config_start(Opts02), + p("net-if (verbosity) res: ~p", [Reason02]), + + p("net-if - incorrect options"), + NetIfOpts3 = [{options, invalid_options}], + Opts03 = [{config, ConfigOpts}, {versions, [v1]}, + {net_if, NetIfOpts3}], + ?line {error, Reason03} = config_start(Opts03), + p("net-if (options) res: ~p", [Reason03]), + + p("server - incorrect timeout (1)"), + ServerOpts1 = [{timeout, invalid_timeout}], + Opts08 = [{config, ConfigOpts}, {versions, [v1]}, + {server, ServerOpts1}], + ?line {error, Reason08} = config_start(Opts08), + p("server (timeout) res: ~p", [Reason08]), + + p("server - incorrect timeout (2)"), + ServerOpts2 = [{timeout, 0}], + Opts09 = [{config, ConfigOpts}, {versions, [v1]}, + {server, ServerOpts2}], + ?line {error, Reason09} = config_start(Opts09), + p("server (timeout) res: ~p", [Reason09]), + + p("server - incorrect timeout (3)"), + ServerOpts3 = [{timeout, -1000}], + Opts10 = [{config, ConfigOpts}, + {versions, [v1]}, + {server, ServerOpts3}], + ?line {error, Reason10} = config_start(Opts10), + p("server (timeout) res: ~p", [Reason10]), + + p("server - incorrect verbosity"), + ServerOpts4 = [{verbosity, invalid_verbosity}], + Opts11 = [{config, ConfigOpts}, + {versions, [v1]}, + {server, ServerOpts4}], + ?line {error, Reason11} = config_start(Opts11), + p("server (verbosity) res: ~p", [Reason11]), + + p("note-store - incorrect timeout (1)"), + NoteStoreOpts1 = [{timeout, invalid_timeout}], + Opts12 = [{config, ConfigOpts}, + {versions, [v1]}, + {note_store, NoteStoreOpts1}], + ?line {error, Reason12} = config_start(Opts12), + p("note-store (timeout) res: ~p", [Reason12]), + + p("note-store - incorrect timeout (2)"), + NoteStoreOpts2 = [{timeout, 0}], + Opts13 = [{config, ConfigOpts}, + {versions, [v1]}, + {note_store, NoteStoreOpts2}], + ?line {error, Reason13} = config_start(Opts13), + p("note-store (timeout) res: ~p", [Reason13]), + + p("note-store - incorrect timeout (3)"), + NoteStoreOpts3 = [{timeout, -2000}], + Opts14 = [{config, ConfigOpts}, + {versions, [v1]}, + {note_store, NoteStoreOpts3}], + ?line {error, Reason14} = config_start(Opts14), + p("note-store (timeout) res: ~p", [Reason14]), + + p("note-store - incorrect verbosity"), + NoteStoreOpts4 = [{timeout, 20000}, {verbosity, invalid_verbosity}], + Opts15 = [{config, ConfigOpts}, + {versions, [v1]}, + {note_store, NoteStoreOpts4}], + ?line {error, Reason15} = config_start(Opts15), + p("note-store (verbosity) res: ~p", [Reason15]), + + p("config - incorrect dir (1)"), + ConfigOpts1 = [{dir, invalid_dir}], + Opts16 = [{config, ConfigOpts1}, + {versions, [v1]}], + ?line {error, Reason16} = config_start(Opts16), + p("config (dir) res: ~p", [Reason16]), + + p("config - incorrect dir (2)"), + ConfigOpts2 = [{dir, "/invalid/dir"}], + Opts17 = [{config, ConfigOpts2}, + {versions, [v1]}], + ?line {error, Reason17} = config_start(Opts17), + p("config (dir) res: ~p", [Reason17]), + + p("config - incorrect verbosity"), + ConfigOpts3 = [{dir, ConfDir}, {verbosity, invalid_verbosity}], + Opts18 = [{config, ConfigOpts3}, + {versions, [v1]}], + ?line {error, Reason18} = config_start(Opts18), + p("config (verbosity) res: ~p", [Reason18]), + + p("mibs - incorrect mibs (1)"), + Mibs1 = invalid_mibs, + Opts19 = [{config, ConfigOpts}, + {versions, [v1]}, + {mibs, Mibs1}], + ?line {error, Reason19} = config_start(Opts19), + p("mibs (mibs) res: ~p", [Reason19]), + + p("mibs - incorrect mibs (2)"), + Mibs2 = [join(StdMibDir, "INVALID-MIB")], + Opts20 = [{config, ConfigOpts}, + {versions, [v1]}, + {mibs, Mibs2}], + ?line {error, Reason20} = config_start(Opts20), + p("mibs (mibs) res: ~p", [Reason20]), + + p("prio - incorrect prio"), + Prio1 = invalid_prio, + Opts21 = [{config, ConfigOpts}, + {versions, [v1]}, + {priority, Prio1}], + ?line {error, Reason21} = config_start(Opts21), + p("prio (prio) res: ~p", [Reason21]), + + p("atl - incorrect type"), + ATL1 = [{type, invalid_type}, + {dir, LogDir}, + {size, {10,10240}}, + {repair, true}], + Opts22 = [{config, ConfigOpts}, + {versions, [v1]}, + {audit_trail_log, ATL1}], + ?line {error, Reason22} = config_start(Opts22), + p("atl (type) res: ~p", [Reason22]), + + p("atl - incorrect dir (1)"), + ATL2 = [{type, read_write}, + {dir, invalid_dir}, + {size, {10,10240}}, + {repair, true}], + Opts23 = [{config, ConfigOpts}, + {versions, [v1]}, + {audit_trail_log, ATL2}], + ?line {error, Reason23} = config_start(Opts23), + p("atl (dir) res: ~p", [Reason23]), + + p("atl - incorrect dir (2)"), + ATL3 = [{type, read_write}, + {dir, "/invalid/dir"}, + {size, {10,10240}}, + {repair, true}], + Opts24 = [{config, ConfigOpts}, + {versions, [v1]}, + {audit_trail_log, ATL3}], + ?line {error, Reason24} = config_start(Opts24), + p("atl (dir) res: ~p", [Reason24]), + + p("atl - incorrect size (1)"), + ATL4 = [{type, read_write}, + {dir, LogDir}, + {size, invalid_size}, + {repair, true}], + Opts25 = [{config, ConfigOpts}, + {versions, [v1]}, + {audit_trail_log, ATL4}], + ?line {error, Reason25} = config_start(Opts25), + p("atl (size) res: ~p", [Reason25]), + + p("atl - incorrect size (2)"), + ATL5 = [{type, read_write}, + {dir, LogDir}, + {size, {10,invalid_file_size}}, + {repair, true}], + Opts26 = [{config, ConfigOpts}, + {versions, [v1]}, + {audit_trail_log, ATL5}], + ?line {error, Reason26} = config_start(Opts26), + p("atl (size) res: ~p", [Reason26]), + + p("atl - incorrect size (3)"), + ATL6 = [{type, read_write}, + {dir, LogDir}, + {size, {invalid_file_num,10240}}, + {repair, true}], + Opts27 = [{config, ConfigOpts}, + {versions, [v1]}, + {audit_trail_log, ATL6}], + ?line {error, Reason27} = config_start(Opts27), + p("atl (size) res: ~p", [Reason27]), + + p("atl - incorrect repair"), + ATL7 = [{type, read_write}, + {dir, LogDir}, + {size, {10,10240}}, + {repair, invalid_repair}], + Opts28 = [{config, ConfigOpts}, + {versions, [v1]}, + {audit_trail_log, ATL7}], + ?line {error, Reason28} = config_start(Opts28), + p("atl (repair) res: ~p", [Reason28]), + + p("version - incorrect versions (1)"), + Vsns1 = invalid_vsns, + Opts29 = [{config, ConfigOpts}, + {versions, Vsns1}], + ?line {error, Reason29} = config_start(Opts29), + p("versions (versions) res: ~p", [Reason29]), + + p("version - incorrect versions (2)"), + Vsns2 = [v1,v2,v3,v9], + Opts30 = [{config, ConfigOpts}, + {versions, Vsns2}], + ?line {error, Reason30} = config_start(Opts30), + p("versions (versions) res: ~p", [Reason30]), + + p("done"), + ok. + + +%% +%% --- +%% + +start_with_invalid_manager_conf_file1(suite) -> []; +start_with_invalid_manager_conf_file1(doc) -> + "Start with invalid manager config file (1)."; +start_with_invalid_manager_conf_file1(Conf) when is_list(Conf) -> + put(tname,swimcf), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + Opts = [{versions, [v1]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + %% -- + p("write manager config file with invalid IP address (1)"), + write_manager_conf(ConfDir, + "arne-anka", "4001", "500", "\"bmkEngine\""), + ?line {error, Reason11} = config_start(Opts), + p("start failed (as expected): ~p", [Reason11]), + ?line {failed_reading, _, _, 1, {parse_error, _}} = Reason11, + await_config_not_running(), + + %% -- + p("write manager config file with invalid IP address (2)"), + write_manager_conf(ConfDir, + "arne_anka", "4001", "500", "\"bmkEngine\""), + ?line {error, Reason12} = config_start(Opts), + p("start failed (as expected): ~p", [Reason12]), + ?line {failed_check, _, _, 2, {invalid_ip_address, _}} = Reason12, + await_config_not_running(), + + %% -- + p("write manager config file with invalid IP address (3)"), + write_manager_conf(ConfDir, + "9999", "4001", "500", "\"bmkEngine\""), + ?line {error, Reason13} = config_start(Opts), + p("start failed (as expected): ~p", [Reason13]), + ?line {failed_check, _, _, 2, {invalid_ip_address, _}} = Reason13, + await_config_not_running(), + + %% -- + p("write manager config file with invalid port (2)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "kalle-anka", "500", "\"bmkEngine\""), + ?line {error, Reason21} = config_start(Opts), + p("start failed (as expected): ~p", [Reason21]), + ?line {failed_reading, _, _, 2, {parse_error, _}} = Reason21, + await_config_not_running(), + + %% -- + p("write manager config file with invalid port (1)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "-1", "500", "\"bmkEngine\""), + ?line {error, Reason22} = config_start(Opts), + p("start failed (as expected): ~p", [Reason22]), + ?line {failed_check, _, _, 3, {invalid_integer, _}} = Reason22, + await_config_not_running(), + + %% -- + p("write manager config file with invalid port (3)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "\"kalle-anka\"", "500", "\"bmkEngine\""), + ?line {error, Reason23} = config_start(Opts), + p("start failed (as expected): ~p", [Reason23]), + ?line {failed_check, _, _, 3, {invalid_integer, _}} = Reason23, + await_config_not_running(), + + %% -- + p("write manager config file with invalid EngineID (1)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "4001", "500", "bmkEngine"), + ?line {error, Reason31} = config_start(Opts), + p("start failed (as expected): ~p", [Reason31]), + ?line {failed_check, _, _, 5, {invalid_string, _}} = Reason31, + await_config_not_running(), + + %% -- + p("write manager config file with invalid EngineID (2)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "4001", "500", "{1,2,3}"), + ?line {error, Reason32} = config_start(Opts), + p("start failed (as expected): ~p", [Reason32]), + ?line {failed_check, _, _, 5, {invalid_string, _}} = Reason32, + await_config_not_running(), + + %% -- + p("write manager config file with invalid EngineID (3)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "4001", "500", "10101"), + ?line {error, Reason33} = config_start(Opts), + p("start failed (as expected): ~p", [Reason33]), + ?line {failed_check, _, _, 5, {invalid_string, _}} = Reason33, + await_config_not_running(), + + %% -- + p("write manager config file with invalid MMS (1)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "4001", "483", "\"bmkEngine\""), + ?line {error, Reason41} = config_start(Opts), + p("start failed (as expected): ~p", [Reason41]), + ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason41, + await_config_not_running(), + + %% -- + p("write manager config file with invalid MMS (2)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "4001", "-1", "\"bmkEngine\""), + ?line {error, Reason42} = config_start(Opts), + p("start failed (as expected): ~p", [Reason42]), + ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason42, + await_config_not_running(), + + %% -- + p("write manager config file with invalid MMS (3)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "4001", "\"kalle-anka\"", "\"bmkEngine\""), + ?line {error, Reason43} = config_start(Opts), + p("start failed (as expected): ~p", [Reason43]), + ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason43, + await_config_not_running(), + + %% -- + p("write manager config file with invalid MMS (4)"), + write_manager_conf(ConfDir, + "[134,138,177,189]", "4001", "kalle_anka", "\"bmkEngine\""), + ?line {error, Reason44} = config_start(Opts), + p("start failed (as expected): ~p", [Reason44]), + ?line {failed_check, _, _, 4, {invalid_integer, _}} = Reason44, + await_config_not_running(), + + %% -- + p("write manager config file with unknown option"), + write_manager_conf(ConfDir, + "{kalle, anka}."), + ?line {error, Reason51} = config_start(Opts), + p("start failed (as expected): ~p", [Reason51]), + ?line {failed_check, _, _, 1, {unknown_config, _}} = Reason51, + await_config_not_running(), + + %% -- + p("write manager config file with unknown option"), + write_manager_conf(ConfDir, + "kalle_anka."), + ?line {error, Reason52} = config_start(Opts), + p("start failed (as expected): ~p", [Reason52]), + ?line {failed_check, _, _, 1, {unknown_config, _}} = Reason52, + await_config_not_running(), + + p("done"), + ok. + + +%% +%% --- +%% + +start_with_invalid_users_conf_file1(suite) -> []; +start_with_invalid_users_conf_file1(doc) -> + "Start with invalid users config file."; +start_with_invalid_users_conf_file1(Conf) when is_list(Conf) -> + put(tname,swiucf), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + Opts = [{versions, [v1]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + write_manager_conf(ConfDir), + + %% -- + p("write users config file with invalid module (1)"), + write_users_conf(ConfDir, [{"kalle", "kalle", "dummy"}]), + ?line {error, Reason11} = config_start(Opts), + p("start failed (as expected): ~p", [Reason11]), + ?line {failed_check, _, _, _, {bad_module, kalle}} = Reason11, + await_config_not_running(), + + %% -- + p("write users config file with invalid module (1)"), + write_users_conf(ConfDir, [{"kalle", "snmpm", "dummy"}]), + ?line {error, Reason12} = config_start(Opts), + p("start failed (as expected): ~p", [Reason12]), + ?line {failed_check, _, _, _, {bad_module, _}} = Reason12, + await_config_not_running(), + + %% -- + p("write users config file with invalid module (2)"), + write_users_conf(ConfDir, [{"kalle1", "10101", "dummy"}]), + ?line {error, Reason13} = config_start(Opts), + p("start failed (as expected): ~p", [Reason13]), + ?line {failed_check, _, _, _, {bad_module, _}} = Reason13, + await_config_not_running(), + + %% -- + p("write users config file with invalid user tuple (1)"), + write_users_conf2(ConfDir, "{kalle, snmpm_user_default}."), + ?line {error, Reason21} = config_start(Opts), + p("start failed (as expected): ~p", [Reason21]), + ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason21, + await_config_not_running(), + + %% -- + p("write users config file with invalid user tuple (2)"), + write_users_conf2(ConfDir, "{kalle, snmpm_user_default, kalle, [], olle}."), + ?line {error, Reason22} = config_start(Opts), + p("start failed (as expected): ~p", [Reason22]), + ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason22, + await_config_not_running(), + + %% -- + p("write users config file with invalid user tuple (3)"), + write_users_conf2(ConfDir, "snmpm_user_default."), + ?line {error, Reason23} = config_start(Opts), + p("start failed (as expected): ~p", [Reason23]), + ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason23, + await_config_not_running(), + + %% -- + p("write users config file with invalid user tuple (4)"), + write_users_conf2(ConfDir, "[kalle, snmpm_user_default, kalle]."), + ?line {error, Reason24} = config_start(Opts), + p("start failed (as expected): ~p", [Reason24]), + ?line {failed_check, _, _, _, {bad_user_config, _}} = Reason24, + await_config_not_running(), + + %% -- + p("write users config file with invalid user agent default config (1)"), + write_users_conf2(ConfDir, "{kalle, snmpm_user_default, kalle, olle}."), + ?line {error, Reason31} = config_start(Opts), + p("start failed (as expected): ~p", [Reason31]), + ?line {failed_check, _, _, _, {bad_default_agent_config, _}} = Reason31, + await_config_not_running(), + + %% -- + p("write users config file with invalid user agent default config (2)"), + write_users_conf2(ConfDir, "{kalle, snmpm_user_default, kalle, [olle]}."), + ?line {error, Reason32} = config_start(Opts), + p("start failed (as expected): ~p", [Reason32]), + %% ?line {failed_check, _, _, _, {bad_default_agent_config, _}} = Reason32, + case Reason32 of + {failed_check, _, _, _, {bad_default_agent_config, _}} -> + ok; + {A, B, C, D} -> + exit({bad_error, A, B, C, D}) + end, + await_config_not_running(), + + p("done"), + ok. + + +%% +%% --- +%% + +start_with_invalid_agents_conf_file1(suite) -> []; +start_with_invalid_agents_conf_file1(doc) -> + "Start with invalid agents config file."; +start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> + put(tname, swiacf), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + Opts = [{versions, [v1]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + write_manager_conf(ConfDir), + + write_users_conf(ConfDir, [{"swiacf", "snmpm_user_default", "dummy"}]), + + Agent0 = {"swiacf", "\"targ-hobbes\"", "\"comm1\"", + "[192,168,0,100]", "162", "\"bmkEngine\"", "1500", "484", "v1", + "any", "\"initial\"", "noAuthNoPriv"}, + + %% -- + p("[test 11] write agents config file with invalid user (1)"), + Agent11 = setelement(1, Agent0, "kalle-anka"), + write_agents_conf(ConfDir, [Agent11]), + case config_start(Opts) of + {error, Reason11} -> + p("start failed (as expected): ~p", [Reason11]), + ?line {failed_reading, _, _, _, {parse_error, _}} = Reason11, + await_config_not_running(); + OK_11 -> + exit({error, {unexpected_success, "11", OK_11}}) + end, + + %% -- + p("[test 21] write agents config file with invalid target name (1)"), + Agent21 = setelement(2, Agent0, "targ-hobbes"), + write_agents_conf(ConfDir, [Agent21]), + case config_start(Opts) of + {error, Reason21} -> + p("start failed (as expected): ~p", [Reason21]), + ?line {failed_reading, _, _, _, {parse_error, _}} = Reason21, + await_config_not_running(); + OK_21 -> + exit({error, {unexpected_success, "21", OK_21}}) + end, + + %% -- + p("[test 22] write agents config file with invalid target name (2)"), + Agent22 = setelement(2, Agent0, "targ_hobbes"), + write_agents_conf(ConfDir, [Agent22]), + case config_start(Opts) of + {error, Reason22} -> + p("start failed (as expected): ~p", [Reason22]), + ?line {failed_check, _, _, _, {invalid_string, _}} = Reason22, + await_config_not_running(); + OK_22 -> + exit({error, {unexpected_success, "22", OK_22}}) + end, + + %% -- + p("[test 23] write agents config file with invalid target name (3)"), + Agent23 = setelement(2, Agent0, "10101"), + write_agents_conf(ConfDir, [Agent23]), + case config_start(Opts) of + {error, Reason23} -> + p("start failed (as expected): ~p", [Reason23]), + ?line {failed_check, _, _, _, {invalid_string, _}} = Reason23, + await_config_not_running(); + OK_23 -> + exit({error, {unexpected_success, "23", OK_23}}) + end, + + %% -- + p("[test 31] write agents config file with invalid community (1)"), + Agent31 = setelement(3, Agent0, "targ-hobbes"), + write_agents_conf(ConfDir, [Agent31]), + case config_start(Opts) of + {error, Reason31} -> + p("start failed (as expected): ~p", [Reason31]), + ?line {failed_reading, _, _, _, {parse_error, _}} = Reason31, + await_config_not_running(); + OK_31 -> + exit({error, {unexpected_success, "31", OK_31}}) + end, + + %% -- + p("[test 32] write agents config file with invalid community (2)"), + Agent32 = setelement(3, Agent0, "targ_hobbes"), + write_agents_conf(ConfDir, [Agent32]), + case config_start(Opts) of + {error, Reason32} -> + p("start failed (as expected): ~p", [Reason32]), + ?line {failed_check, _, _, _, {invalid_string, _}} = Reason32, + await_config_not_running(); + OK_32 -> + exit({error, {unexpected_success, "32", OK_32}}) + end, + + %% -- + p("[test 33] write agents config file with invalid community (3)"), + Agent33 = setelement(3, Agent0, "10101"), + write_agents_conf(ConfDir, [Agent33]), + case config_start(Opts) of + {error, Reason33} -> + p("start failed (as expected): ~p", [Reason33]), + ?line {failed_check, _, _, _, {invalid_string, _}} = Reason33, + await_config_not_running(); + OK_33 -> + exit({error, {unexpected_success, "33", OK_33}}) + end, + + %% -- + p("[test 51] write agents config file with invalid ip (1)"), + Agent51 = setelement(4, Agent0, "kalle_anka"), + write_agents_conf(ConfDir, [Agent51]), + case config_start(Opts) of + {error, Reason51} -> + p("start failed (as expected): ~p", [Reason51]), + ?line {failed_check, _, _, _, {bad_address, _}} = Reason51, + await_config_not_running(); + OK_51 -> + exit({error, {unexpected_success, "51", OK_51}}) + end, + + %% -- + p("[test 52] write agents config file with invalid ip (2)"), + Agent52 = setelement(4, Agent0, "10101"), + write_agents_conf(ConfDir, [Agent52]), + case config_start(Opts) of + {error, Reason52} -> + p("start failed (as expected): ~p", [Reason52]), + ?line {failed_check, _, _, _, {bad_address, _}} = Reason52, + await_config_not_running(); + OK_52 -> + exit({error, {unexpected_success, "52", OK_52}}) + end, + + %% -- + p("[test 53] write agents config file with invalid ip (3)"), + Agent53 = setelement(4, Agent0, "[192,168,0]"), + write_agents_conf(ConfDir, [Agent53]), + case config_start(Opts) of + {error, Reason53} -> + p("start failed (as expected): ~p", [Reason53]), + ?line {failed_check, _, _, _, {invalid_ip_address, _}} = Reason53, + await_config_not_running(); + OK_53 -> + exit({error, {unexpected_success, "53", OK_53}}) + end, + + %% -- + p("[test 54] write agents config file with invalid ip (4)"), + Agent54 = setelement(4, Agent0, "[192,168,0,100,99]"), + write_agents_conf(ConfDir, [Agent54]), + case config_start(Opts) of + {error, Reason54} -> + p("start failed (as expected): ~p", [Reason54]), + ?line {failed_check, _, _, _, {invalid_ip_address, _}} = Reason54, + await_config_not_running(); + OK_54 -> + exit({error, {unexpected_success, "54", OK_54}}) + end, + + %% -- + p("[test 55] write agents config file with invalid ip (5)"), + Agent55 = setelement(4, Agent0, "[192,168,0,arne]"), + write_agents_conf(ConfDir, [Agent55]), + ?line {error, Reason55} = config_start(Opts), + p("start failed (as expected): ~p", [Reason55]), + ?line {failed_check, _, _, _, {invalid_ip_address, _}} = Reason55, + await_config_not_running(), + + %% -- + p("[test 61] write agents config file with invalid port (1)"), + Agent61 = setelement(5, Agent0, "kalle_anka"), + write_agents_conf(ConfDir, [Agent61]), + ?line {error, Reason61} = config_start(Opts), + p("start failed (as expected): ~p", [Reason61]), + ?line {failed_check, _, _, _, {invalid_integer, _}} = Reason61, + await_config_not_running(), + + %% -- + p("[test 62] write agents config file with invalid port (2)"), + Agent62 = setelement(5, Agent0, "-1"), + write_agents_conf(ConfDir, [Agent62]), + ?line {error, Reason62} = config_start(Opts), + p("start failed (as expected): ~p", [Reason62]), + ?line {failed_check, _, _, _, {invalid_integer, _}} = Reason62, + await_config_not_running(), + + %% -- + p("[test 63] write agents config file with invalid port (3)"), + Agent63 = setelement(5, Agent0, "\"100\""), + write_agents_conf(ConfDir, [Agent63]), + ?line {error, Reason63} = config_start(Opts), + p("start failed (as expected): ~p", [Reason63]), + ?line {failed_check, _, _, _, {invalid_integer, _}} = Reason63, + await_config_not_running(), + + %% -- + p("[test 71] write agents config file with invalid engine-id (1)"), + Agent71 = setelement(6, Agent0, "kalle_anka"), + write_agents_conf(ConfDir, [Agent71]), + ?line {error, Reason71} = config_start(Opts), + p("start failed (as expected): ~p", [Reason71]), + ?line {failed_check, _, _, _, {invalid_string, _}} = Reason71, + await_config_not_running(), + + %% -- + p("[test 72] write agents config file with invalid engine-id (2)"), + Agent72 = setelement(6, Agent0, "10101"), + write_agents_conf(ConfDir, [Agent72]), + ?line {error, Reason72} = config_start(Opts), + p("start failed (as expected): ~p", [Reason72]), + ?line {failed_check, _, _, _, {invalid_string, _}} = Reason72, + await_config_not_running(), + + %% -- + p("[test 81] write agents config file with invalid timeout (1)"), + Agent81 = setelement(7, Agent0, "kalle_anka"), + write_agents_conf(ConfDir, [Agent81]), + ?line {error, Reason81} = config_start(Opts), + p("start failed (as expected): ~p", [Reason81]), + ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason81, + await_config_not_running(), + + %% -- + p("[test 82] write agents config file with invalid timeout (2)"), + Agent82 = setelement(7, Agent0, "-1"), + write_agents_conf(ConfDir, [Agent82]), + ?line {error, Reason82} = config_start(Opts), + p("start failed (as expected): ~p", [Reason82]), + ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason82, + await_config_not_running(), + + %% -- + p("[test 83] write agents config file with invalid timeout (3)"), + Agent83 = setelement(7, Agent0, "{1000, 1, 10, kalle}"), + write_agents_conf(ConfDir, [Agent83]), + ?line {error, Reason83} = config_start(Opts), + p("start failed (as expected): ~p", [Reason83]), + ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason83, + await_config_not_running(), + + %% -- + p("[test 84] write agents config file with invalid timeout (4)"), + Agent84 = setelement(7, Agent0, "{1000, -1, 10, 10}"), + write_agents_conf(ConfDir, [Agent84]), + ?line {error, Reason84} = config_start(Opts), + p("start failed (as expected): ~p", [Reason84]), + ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason84, + await_config_not_running(), + + %% -- + p("[test 85] write agents config file with invalid timeout (5)"), + Agent85 = setelement(7, Agent0, "{1000, 1, -100, 10}"), + write_agents_conf(ConfDir, [Agent85]), + ?line {error, Reason85} = config_start(Opts), + p("start failed (as expected): ~p", [Reason85]), + ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason85, + await_config_not_running(), + + %% -- + p("[test 86] write agents config file with invalid timeout (6)"), + Agent86 = setelement(7, Agent0, "{1000, 1, 100, -1}"), + write_agents_conf(ConfDir, [Agent86]), + ?line {error, Reason86} = config_start(Opts), + p("start failed (as expected): ~p", [Reason86]), + ?line {failed_check, _, _, _, {invalid_timer, _}} = Reason86, + await_config_not_running(), + + %% -- + p("[test 91] write agents config file with invalid max-message-size (1)"), + Agent91 = setelement(8, Agent0, "483"), + write_agents_conf(ConfDir, [Agent91]), + ?line {error, Reason91} = config_start(Opts), + p("start failed (as expected): ~p", [Reason91]), + ?line {failed_check, _, _, _, {invalid_packet_size, _}} = Reason91, + await_config_not_running(), + + %% -- + p("[test 92] write agents config file with invalid max-message-size (2)"), + Agent92 = setelement(8, Agent0, "kalle_anka"), + write_agents_conf(ConfDir, [Agent92]), + ?line {error, Reason92} = config_start(Opts), + p("start failed (as expected): ~p", [Reason92]), + ?line {failed_check, _, _, _, {invalid_packet_size, _}} = Reason92, + await_config_not_running(), + + %% -- + p("[test A1] write agents config file with invalid version (1)"), + AgentA1 = setelement(9, Agent0, "1"), + write_agents_conf(ConfDir, [AgentA1]), + ?line {error, ReasonA1} = config_start(Opts), + p("start failed (as expected): ~p", [ReasonA1]), + ?line {failed_check, _, _, _, {bad_version, _}} = ReasonA1, + await_config_not_running(), + + %% -- + p("[test A2] write agents config file with invalid version (2)"), + AgentA2 = setelement(9, Agent0, "v30"), + write_agents_conf(ConfDir, [AgentA2]), + ?line {error, ReasonA2} = config_start(Opts), + p("start failed (as expected): ~p", [ReasonA2]), + ?line {failed_check, _, _, _, {bad_version, _}} = ReasonA2, + await_config_not_running(), + + %% -- + p("[test B1] write agents config file with invalid sec-model (1)"), + AgentB1 = setelement(10, Agent0, "\"any\""), + write_agents_conf(ConfDir, [AgentB1]), + ?line {error, ReasonB1} = config_start(Opts), + p("start failed (as expected): ~p", [ReasonB1]), + ?line {failed_check, _, _, _, {invalid_sec_model, _}} = ReasonB1, + await_config_not_running(), + + %% -- + p("[test B2] write agents config file with invalid sec-model (2)"), + AgentB2 = setelement(10, Agent0, "v3"), + write_agents_conf(ConfDir, [AgentB2]), + ?line {error, ReasonB2} = config_start(Opts), + p("start failed (as expected): ~p", [ReasonB2]), + ?line {failed_check, _, _, _, {invalid_sec_model, _}} = ReasonB2, + await_config_not_running(), + + %% -- + p("[test C1] write agents config file with invalid sec-name (1)"), + AgentC1 = setelement(11, Agent0, "initial"), + write_agents_conf(ConfDir, [AgentC1]), + case config_start(Opts) of + {error, ReasonC1} -> + p("start failed (as expected): ~p", [ReasonC1]), + ?line {failed_check, _, _, _, {bad_sec_name, _}} = ReasonC1, + await_config_not_running(); + OK_C1 -> + exit({error, {unexpected_success, "C1", OK_C1}}) + end, + + %% -- + p("[test C2] write agents config file with invalid sec-name (2)"), + AgentC2 = setelement(11, Agent0, "10101"), + write_agents_conf(ConfDir, [AgentC2]), + case config_start(Opts) of + {error, ReasonC2} -> + p("start failed (as expected): ~p", [ReasonC2]), + ?line {failed_check, _, _, _, {bad_sec_name, _}} = ReasonC2, + await_config_not_running(); + OK_C2 -> + exit({error, {unexpected_success, "C2", OK_C2}}) + end, + + %% -- + p("[test D1] write agents config file with invalid sec-level (1)"), + AgentD1 = setelement(12, Agent0, "\"noAuthNoPriv\""), + write_agents_conf(ConfDir, [AgentD1]), + case config_start(Opts) of + {error, ReasonD1} -> + p("start failed (as expected): ~p", [ReasonD1]), + ?line {failed_check, _, _, _, {invalid_sec_level, _}} = ReasonD1, + await_config_not_running(); + OK_D1 -> + exit({error, {unexpected_success, "D1", OK_D1}}) + end, + + %% -- + p("[test D2] write agents config file with invalid sec-level (2)"), + AgentD2 = setelement(12, Agent0, "99"), + write_agents_conf(ConfDir, [AgentD2]), + case config_start(Opts) of + {error, ReasonD2} -> + p("start failed (as expected): ~p", [ReasonD2]), + ?line {failed_check, _, _, _, {invalid_sec_level, _}} = ReasonD2, + await_config_not_running(); + OK_D2 -> + exit({error, {unexpected_success, "D2", OK_D2}}) + end, + + %% -- + p("[test E1] write agents config file with invalid agent (1)"), + write_agents_conf2(ConfDir, "{swiacf, \"targ-hobbes\"}."), + case config_start(Opts) of + {error, ReasonE1} -> + p("start failed (as expected): ~p", [ReasonE1]), + ?line {failed_check, _, _, _, {bad_agent_config, _}} = ReasonE1, + await_config_not_running(); + OK_E1 -> + exit({error, {unexpected_success, "E1", OK_E1}}) + end, + + p("done"), + ok. + + +%% +%% --- +%% + +start_with_invalid_usm_conf_file1(suite) -> []; +start_with_invalid_usm_conf_file1(doc) -> + "Start with invalid usm config file."; +start_with_invalid_usm_conf_file1(Conf) when is_list(Conf) -> + put(tname,swiusmcf), + p("start"), + process_flag(trap_exit, true), + + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + Opts = [{versions, [v1,v2,v3]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + write_manager_conf(ConfDir), + + write_users_conf(ConfDir, [{"swiacf", "snmpm_user_default", "dummy"}]), + + Usm0 = {"\"bmkEngine\"", "\"swiusmcf\"", + "usmNoAuthProtocol", "[]", + "usmNoPrivProtocol", "[]"}, + + Usm1 = {"\"bmkEngine\"", "\"swiusmcf\"", "\"kalle\"", + "usmNoAuthProtocol", "[]", + "usmNoPrivProtocol", "[]"}, + + %% -- + p("[test 11] write usm config file with invalid engine-id (1)"), + Usm11 = setelement(1, Usm0, "kalle-anka"), + write_usm_conf(ConfDir, [Usm11]), + ?line {error, Reason11} = config_start(Opts), + p("start failed (as expected): ~p", [Reason11]), + ?line {failed_reading, _, _, _, {parse_error, _}} = Reason11, + await_config_not_running(), + + %% -- + p("[test 12] write usm config file with invalid engine-id (2)"), + Usm12 = setelement(1, Usm0, "kalle_anka"), + write_usm_conf(ConfDir, [Usm12]), + ?line {error, Reason12} = config_start(Opts), + p("start failed (as expected): ~p", [Reason12]), + ?line {failed_check, _, _, _, {bad_usm_engine_id, _}} = Reason12, + await_config_not_running(), + + %% -- + p("[test 13] write usm config file with invalid engine-id (3)"), + Usm13 = setelement(1, Usm1, "10101"), + write_usm_conf(ConfDir, [Usm13]), + ?line {error, Reason13} = config_start(Opts), + p("start failed (as expected): ~p", [Reason13]), + ?line {failed_check, _, _, _, {bad_usm_engine_id, _}} = Reason13, + await_config_not_running(), + + %% -- + p("[test 21] write usm config file with invalid user-name (1)"), + Usm21 = setelement(2, Usm0, "kalle_anka"), + write_usm_conf(ConfDir, [Usm21]), + ?line {error, Reason21} = config_start(Opts), + p("start failed (as expected): ~p", [Reason21]), + ?line {failed_check, _, _, _, {bad_usm_user_name, _}} = Reason21, + await_config_not_running(), + + %% -- + p("[test 22] write usm config file with invalid user-name (1)"), + Usm22 = setelement(2, Usm1, "10101"), + write_usm_conf(ConfDir, [Usm22]), + ?line {error, Reason22} = config_start(Opts), + p("start failed (as expected): ~p", [Reason22]), + ?line {failed_check, _, _, _, {bad_usm_user_name, _}} = Reason22, + await_config_not_running(), + + %% -- + p("[test 31] write usm config file with invalid sec-name (1)"), + Usm31 = setelement(3, Usm1, "kalle_anka"), + write_usm_conf(ConfDir, [Usm31]), + ?line {error, Reason31} = config_start(Opts), + p("start failed (as expected): ~p", [Reason31]), + ?line {failed_check, _, _, _, {bad_usm_sec_name, _}} = Reason31, + await_config_not_running(), + + %% -- + p("[test 32] write usm config file with invalid sec-name (2)"), + Usm32 = setelement(3, Usm1, "10101"), + write_usm_conf(ConfDir, [Usm32]), + ?line {error, Reason32} = config_start(Opts), + p("start failed (as expected): ~p", [Reason32]), + ?line {failed_check, _, _, _, {bad_usm_sec_name, _}} = Reason32, + await_config_not_running(), + + %% -- + p("[test 41] write usm config file with invalid auth-protocol (1)"), + Usm41 = setelement(3, Usm0, "\"usmNoAuthProtocol\""), + write_usm_conf(ConfDir, [Usm41]), + ?line {error, Reason41} = config_start(Opts), + p("start failed (as expected): ~p", [Reason41]), + ?line {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason41, + await_config_not_running(), + + %% -- + p("[test 42] write usm config file with invalid auth-protocol (2)"), + Usm42 = setelement(3, Usm0, "kalle"), + write_usm_conf(ConfDir, [Usm42]), + ?line {error, Reason42} = config_start(Opts), + p("start failed (as expected): ~p", [Reason42]), + ?line {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason42, + await_config_not_running(), + + %% -- + p("[test 43] write usm config file with invalid auth-protocol (3)"), + Usm43 = setelement(3, Usm0, "10101"), + write_usm_conf(ConfDir, [Usm43]), + ?line {error, Reason43} = config_start(Opts), + p("start failed (as expected): ~p", [Reason43]), + ?line {failed_check, _, _, _, {invalid_auth_protocol, _}} = Reason43, + await_config_not_running(), + + %% -- + p("[test 51] write usm config file with invalid auth-key (1)"), + Usm51 = setelement(3, Usm0, "usmHMACMD5AuthProtocol"), + write_usm_conf(ConfDir, [Usm51]), + ?line {error, Reason51} = config_start(Opts), + p("start failed (as expected): ~p", [Reason51]), + ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason51, + await_config_not_running(), + + %% -- + p("[test 52] write usm config file with invalid auth-key (2)"), + Usm52 = setelement(4, Usm51, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5]"), + write_usm_conf(ConfDir, [Usm52]), + ?line {error, Reason52} = config_start(Opts), + p("start failed (as expected): ~p", [Reason52]), + ?line {failed_check, _, _, _, {invalid_auth_key, _, 15}} = Reason52, + await_config_not_running(), + + %% -- + p("[test 53] write usm config file with invalid auth-key (3)"), + Usm53 = setelement(4, Usm51, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7]"), + write_usm_conf(ConfDir, [Usm53]), + ?line {error, Reason53} = config_start(Opts), + p("start failed (as expected): ~p", [Reason53]), + ?line {failed_check, _, _, _, {invalid_auth_key, _, 17}} = Reason53, + await_config_not_running(), + + %% -- + p("[test 54] write usm config file with invalid auth-key (4)"), + Usm54 = setelement(4, Usm51, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,kalle]"), + write_usm_conf(ConfDir, [Usm54]), + %% ?line ok = crypto:start(), %% Varf�r k�r den redan? + ?line crypto:start(), %% Make sure it's started... + ?line {error, Reason54} = config_start(Opts), + ?line ok = crypto:stop(), + p("start failed (as expected): ~p", [Reason54]), + ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason54, + await_config_not_running(), + + %% -- + p("[test 55] write usm config file with invalid auth-key (5)"), + Usm55 = setelement(4, Usm51, "arne_anka"), + write_usm_conf(ConfDir, [Usm55]), + ?line {error, Reason55} = config_start(Opts), + p("start failed (as expected): ~p", [Reason55]), + ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason55, + await_config_not_running(), + + %% -- + p("[test 56] write usm config file with invalid auth-key (6)"), + Usm56 = setelement(4, Usm51, "10101"), + write_usm_conf(ConfDir, [Usm56]), + ?line {error, Reason56} = config_start(Opts), + p("start failed (as expected): ~p", [Reason56]), + ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason56, + await_config_not_running(), + + %% -- + p("[test 57] write usm config file with invalid auth-key (7)"), + Usm57 = setelement(3, Usm0, "usmHMACSHAAuthProtocol"), + write_usm_conf(ConfDir, [Usm57]), + ?line {error, Reason57} = config_start(Opts), + p("start failed (as expected): ~p", [Reason57]), + ?line {failed_check, _, _, _, {invalid_auth_key, _, _}} = Reason57, + await_config_not_running(), + + %% -- + p("[test 58] write usm config file with invalid auth-key (8)"), + Usm58 = setelement(4, Usm57, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]"), + write_usm_conf(ConfDir, [Usm58]), + ?line {error, Reason58} = config_start(Opts), + p("start failed (as expected): ~p", [Reason58]), + ?line {failed_check, _, _, _, {invalid_auth_key, _, 16}} = Reason58, + await_config_not_running(), + + %% -- + p("[test 59] write usm config file with invalid auth-key (9)"), + Usm59 = setelement(4, Usm57, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,ka]"), + write_usm_conf(ConfDir, [Usm59]), + ?line ok = crypto:start(), + ?line {error, Reason59} = config_start(Opts), + ?line ok = crypto:stop(), + p("start failed (as expected): ~p", [Reason59]), + ?line {failed_check, _, _, _, {invalid_auth_key, _}} = Reason59, + await_config_not_running(), + + %% -- + p("[test 5A] write usm config file with valid auth-key when crypto not started (10)"), + Usm5A = setelement(4, Usm57, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]"), + write_usm_conf(ConfDir, [Usm5A]), + ?line {error, Reason5A} = config_start(Opts), + p("start failed (as expected): ~p", [Reason5A]), + ?line {failed_check, _, _, _, {unsupported_crypto, _}} = Reason5A, + await_config_not_running(), + + %% -- + p("[test 61] write usm config file with invalid priv-protocol (1)"), + Usm61 = setelement(5, Usm0, "\"usmNoPrivProtocol\""), + write_usm_conf(ConfDir, [Usm61]), + ?line {error, Reason61} = config_start(Opts), + p("start failed (as expected): ~p", [Reason61]), + ?line {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason61, + await_config_not_running(), + + %% -- + p("[test 62] write usm config file with invalid priv-protocol (2)"), + Usm62 = setelement(5, Usm0, "kalle"), + write_usm_conf(ConfDir, [Usm62]), + ?line {error, Reason62} = config_start(Opts), + p("start failed (as expected): ~p", [Reason62]), + ?line {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason62, + await_config_not_running(), + + %% -- + p("[test 63] write usm config file with invalid priv-protocol (3)"), + Usm63 = setelement(5, Usm0, "10101"), + write_usm_conf(ConfDir, [Usm63]), + ?line {error, Reason63} = config_start(Opts), + p("start failed (as expected): ~p", [Reason63]), + ?line {failed_check, _, _, _, {invalid_priv_protocol, _}} = Reason63, + await_config_not_running(), + + %% -- + p("[test 71] write usm config file with invalid priv-key (1)"), + Usm71 = setelement(5, Usm0, "usmDESPrivProtocol"), + write_usm_conf(ConfDir, [Usm71]), + ?line {error, Reason71} = config_start(Opts), + p("start failed (as expected): ~p", [Reason71]), + ?line {failed_check, _, _, _, {invalid_priv_key, _, _}} = Reason71, + await_config_not_running(), + + %% -- + p("[test 72] write usm config file with invalid priv-key (2)"), + Usm72 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5]"), + write_usm_conf(ConfDir, [Usm72]), + ?line {error, Reason72} = config_start(Opts), + p("start failed (as expected): ~p", [Reason72]), + ?line {failed_check, _, _, _, {invalid_priv_key, _, 15}} = Reason72, + await_config_not_running(), + + %% -- + p("[test 73] write usm config file with invalid priv-key (3)"), + Usm73 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7]"), + write_usm_conf(ConfDir, [Usm73]), + ?line {error, Reason73} = config_start(Opts), + p("start failed (as expected): ~p", [Reason73]), + ?line {failed_check, _, _, _, {invalid_priv_key, _, 17}} = Reason73, + await_config_not_running(), + + %% -- + p("[test 74] write usm config file with invalid priv-key (4)"), + Usm74 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,kalle]"), + write_usm_conf(ConfDir, [Usm74]), + ?line ok = crypto:start(), + ?line {error, Reason74} = config_start(Opts), + ?line ok = crypto:stop(), + p("start failed (as expected): ~p", [Reason74]), + ?line {failed_check, _, _, _, {invalid_priv_key, _}} = Reason74, + await_config_not_running(), + + %% -- + p("[test 75] write usm config file with invalid priv-key (5)"), + Usm75 = setelement(6, Usm71, "arne_anka"), + write_usm_conf(ConfDir, [Usm75]), + ?line {error, Reason75} = config_start(Opts), + p("start failed (as expected): ~p", [Reason75]), + ?line {failed_check, _, _, _, {invalid_priv_key, _}} = Reason75, + await_config_not_running(), + + %% -- + p("[test 76] write usm config file with invalid priv-key (6)"), + Usm76 = setelement(6, Usm71, "10101"), + write_usm_conf(ConfDir, [Usm76]), + ?line {error, Reason76} = config_start(Opts), + p("start failed (as expected): ~p", [Reason76]), + ?line {failed_check, _, _, _, {invalid_priv_key, _}} = Reason76, + await_config_not_running(), + + %% -- + p("[test 77] write usm config file with valid priv-key when crypto not started (7)"), + Usm77 = setelement(6, Usm71, "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]"), + write_usm_conf(ConfDir, [Usm77]), + ?line {error, Reason77} = config_start(Opts), + p("start failed (as expected): ~p", [Reason77]), + ?line {failed_check, _, _, _, {unsupported_crypto, _}} = Reason77, + await_config_not_running(), + + %% -- + p("[test 78] write usm config file with invalid usm (1)"), + write_usm_conf2(ConfDir, "{\"bmkEngine\", \"swiusmcf\"}."), + ?line {error, Reason81} = config_start(Opts), + p("start failed (as expected): ~p", [Reason81]), + ?line {failed_check, _, _, _, {bad_usm_config, _}} = Reason81, + await_config_not_running(), + + p("done"), + ok. + + +%% +%% --- +%% + +normal_op(doc) -> + "A collection of tests for normal operation"; +normal_op(suite) -> + [ + system, + agents, + users, + usm_users, + counter, + stats_counter + ]. + + +%% +%% --- +%% + +system(doc) -> + "Various system related operations with the snmp manager config"; +system(suite) -> + [ + simple_system_op + ]. + +simple_system_op(suite) -> []; +simple_system_op(doc) -> + "Access some of the known system info and some \n" + "system info that does not exist."; +simple_system_op(Conf) when is_list(Conf) -> + put(tname,sso), + p("start"), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{versions, [v1]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("start config"), + ?line {ok, _Pid} = config_start(Opts), + + p("retreive various configs"), + ?line {ok, _Time} = snmpm_config:system_start_time(), + ?line {ok, _EngineId} = snmpm_config:get_engine_id(), + ?line {ok, _MMS} = snmpm_config:get_engine_max_message_size(), + + p("attempt to retreive nonexisting"), + ?line {error, not_found} = snmpm_config:system_info(kalle), + + ?line ok = config_stop(), + await_config_not_running(), + + p("done"), + ok. + + +%% +%% --- +%% + +users(doc) -> + "Various users related operations with the snmp manager config"; +users(suite) -> + [ + register_user_using_file, + register_user_using_function, + register_user_failed_using_function1 + ]. + + +%% +%% --- +%% + +register_user_using_file(suite) -> []; +register_user_using_file(doc) -> + "Register user using the 'users.conf' file."; +register_user_using_file(Conf) when is_list(Conf) -> + put(tname,ruufi), + p("start"), + process_flag(trap_exit, true), + _ConfDir = ?config(manager_conf_dir, Conf), + _DbDir = ?config(manager_db_dir, Conf), + ?SKIP(not_yet_implemented). + + +%% +%% --- +%% + +register_user_using_function(suite) -> []; +register_user_using_function(doc) -> + "Register user using the API (function)."; +register_user_using_function(Conf) when is_list(Conf) -> + put(tname,ruufu), + p("start"), + process_flag(trap_exit, true), + _ConfDir = ?config(manager_conf_dir, Conf), + _DbDir = ?config(manager_db_dir, Conf), + ?SKIP(not_yet_implemented). + + +%% +%% --- +%% + +register_user_failed_using_function1(suite) -> []; +register_user_failed_using_function1(doc) -> + "Register user failed using incorrect arguments to API (function)."; +register_user_failed_using_function1(Conf) when is_list(Conf) -> + put(tname,rufufu1), + p("start"), + process_flag(trap_exit, true), + _ConfDir = ?config(manager_conf_dir, Conf), + _DbDir = ?config(manager_db_dir, Conf), + ?SKIP(not_yet_implemented). + + +%% +%% --- +%% + +agents(doc) -> + "Various agents related operations with the snmp manager config"; +agents(suite) -> + [ + register_agent_using_file, + register_agent_using_function, + register_agent_failed_using_function1 + ]. + + +%% +%% --- +%% + +register_agent_using_file(suite) -> []; +register_agent_using_file(doc) -> + "Register agents using the 'agents'conf' file."; +register_agent_using_file(Conf) when is_list(Conf) -> + put(tname,raufi), + p("start"), + process_flag(trap_exit, true), + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + Opts = [{versions, [v1]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + + %% -- + p("write manager config file"), + write_manager_conf(ConfDir), + + %% -- + p("write users config file"), + UserId1 = raufi1, + UserId1Str = str(UserId1), + UserId2 = raufi2, + UserId2Str = str(UserId2), + User1 = {UserId1Str, "snmpm_user_default", "dummy1"}, + User2 = {UserId2Str, "snmpm_user_default", "dummy2", "[{version, v1}]"}, + write_users_conf(ConfDir, [User1, User2]), + + %% -- + p("write agents config file"), + AgentAddr1 = [192,168,0,101], + AgentAddr1Str = str(AgentAddr1), + AgentPort1 = 162, + AgentPort1Str = str(AgentPort1), + EngineID1 = "bmkEngine1", + EngineID1Str = str(EngineID1), + MMS1 = 1024, + MMS1Str = str(MMS1), + AgentAddr2 = [192,168,0,102], + AgentAddr2Str = str(AgentAddr2), + AgentPort2 = 162, + AgentPort2Str = str(AgentPort2), + EngineID2 = "bmkEngine2", + EngineID2Str = str(EngineID2), + MMS2 = 512, + MMS2Str = str(MMS2), + Agent1Str = {UserId1Str, "\"targ-hobbes1\"", "\"comm\"", + AgentAddr1Str, AgentPort1Str, EngineID1Str, + "1000", MMS1Str, "v1", + "any", "\"initial\"", "noAuthNoPriv"}, + Agent2Str = {UserId2Str, "\"targ-hobbes2\"", "\"comm\"", + AgentAddr2Str, AgentPort2Str, EngineID2Str, + "1500", MMS2Str, "v1", + "any", "\"initial\"", "noAuthNoPriv"}, + write_agents_conf(ConfDir, [Agent1Str, Agent2Str]), + + %% -- + p("start the config process"), + ?line {ok, _Pid} = config_start(Opts), + + %% -- + p("which agents"), + ?line [_, _] = All = snmpm_config:which_agents(), + p("all agents: ~n ~p", [All]), + ?line [A1] = snmpm_config:which_agents(UserId1), + p("agents belonging to ~w: ~n ~p", [UserId1, A1]), + ?line [A2] = snmpm_config:which_agents(UserId2), + p("agents belonging to ~w: ~n ~p", [UserId2, A2]), + + %% -- + p("All info for agent <~w,~w>", [AgentAddr1, AgentPort1]), + ?line {ok, AllInfo1} = + snmpm_config:agent_info(AgentAddr1, AgentPort1, all), + p("all agent info for agent: ~n ~p", [AllInfo1]), + + %% -- + p("EngineID (~p) for agent <~w,~w>", [EngineID1, AgentAddr1, AgentPort1]), + ?line {ok, EngineID1} = + snmpm_config:agent_info(AgentAddr1, AgentPort1, engine_id), + + + %% -- + p("All info for agent <~w,~w>", [AgentAddr2, AgentPort2]), + ?line {ok, AllInfo2} = + snmpm_config:agent_info(AgentAddr2, AgentPort2, all), + p("all agent info for agent: ~n ~p", [AllInfo2]), + + %% -- + p("EngineID (~p) for agent <~w,~w>", [EngineID2, AgentAddr2, AgentPort2]), + ?line {ok, EngineID2} = + snmpm_config:agent_info(AgentAddr2, AgentPort2, engine_id), + + %% -- + ?line {ok, MMS2} = + snmpm_config:agent_info(AgentAddr2, AgentPort2, max_message_size), + NewMMS21 = 2048, + p("try update agent info max-message-size to ~w for agent <~w,~w>", + [NewMMS21, AgentAddr2, AgentPort2]), + ?line ok = snmpm_config:update_agent_info(UserId2, AgentAddr2, AgentPort2, + max_message_size, NewMMS21), + ?line {ok, NewMMS21} = + snmpm_config:agent_info(AgentAddr2, AgentPort2, max_message_size), + + %% -- + p("try (and fail) to update agent info max-message-size to ~w " + "for agent <~w,~w> " + "with user ~w (not owner)", + [NewMMS21, AgentAddr2, AgentPort2, UserId1]), + ?line {error, Reason01} = + snmpm_config:update_agent_info(UserId1, AgentAddr2, AgentPort2, + max_message_size, NewMMS21), + p("expected failure. Reason01: ~p", [Reason01]), + ?line {ok, NewMMS21} = + snmpm_config:agent_info(AgentAddr2, AgentPort2, max_message_size), + + %% -- + NewMMS22 = 400, + p("try (and fail) to update agent info max-message-size to ~w " + "for agent <~w,~w>", + [NewMMS22, AgentAddr2, AgentPort2]), + ?line {error, Reason02} = + snmpm_config:update_agent_info(UserId1, AgentAddr2, AgentPort2, + max_message_size, NewMMS22), + p("expected failure. Reason02: ~p", [Reason02]), + + %% -- + p("stop config process"), + ?line ok = snmpm_config:stop(), + await_config_not_running(), + + %% -- + p("done"), + ok. + + +%% +%% --- +%% + +register_agent_using_function(suite) -> []; +register_agent_using_function(doc) -> + "Register agents using the API (function)."; +register_agent_using_function(Conf) when is_list(Conf) -> + put(tname,raufu), + p("start"), + process_flag(trap_exit, true), + _ConfDir = ?config(manager_conf_dir, Conf), + _DbDir = ?config(manager_db_dir, Conf), + ?SKIP(not_yet_implemented). + + +%% +%% --- +%% + +register_agent_failed_using_function1(suite) -> []; +register_agent_failed_using_function1(doc) -> + "Register agents failng using the API (function) with incorrect " + "config (1)."; +register_agent_failed_using_function1(Conf) when is_list(Conf) -> + put(tname,rafuf1), + p("start"), + process_flag(trap_exit, true), + _ConfDir = ?config(manager_conf_dir, Conf), + _DbDir = ?config(manager_db_dir, Conf), + ?SKIP(not_yet_implemented). + + +%% +%% --- +%% + +usm_users(doc) -> + "Various USM users related operations with the snmp manager config"; +usm_users(suite) -> + [ + register_usm_user_using_file, + register_usm_user_using_function, + register_usm_user_failed_using_function1, + update_usm_user_info + ]. + + +%% +%% --- +%% + +register_usm_user_using_file(suite) -> []; +register_usm_user_using_file(doc) -> + "Register usm user using the 'usm.conf' file."; +register_usm_user_using_file(Conf) when is_list(Conf) -> + put(tname,ruuufi), + p("start"), + process_flag(trap_exit, true), + + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + Opts = [{versions, [v3]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + %% -- + p("write manager config file"), + write_manager_conf(ConfDir), + + %% -- + p("write usm user config file"), + SecEngineID = "loctzp's engine", + SecName1 = "samu_auth1", + UserName1 = SecName1, + UsmUser1 = {"\"" ++ SecEngineID ++ "\"", + "\"" ++ UserName1 ++ "\"", + "\"" ++ SecName1 ++ "\"", + "usmHMACMD5AuthProtocol", "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]", + "usmNoPrivProtocol", "[]"}, + + SecName2 = "samu_auth2", + UserName2 = "samu", + UsmUser2 = {"\"" ++ SecEngineID ++ "\"", + "\"" ++ UserName2 ++ "\"", + "\"" ++ SecName2 ++ "\"", + "usmHMACMD5AuthProtocol", "[1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]", + "usmNoPrivProtocol", "[]"}, + write_usm_conf(ConfDir, [UsmUser1, UsmUser2]), + + %% -- + p("start the config process"), + ?line {ok, _Pid} = config_start(Opts), + + %% -- + p("lookup 1 (ok)"), + ?line {ok, #usm_user{name = UserName1} = User1} = + snmpm_config:get_usm_user_from_sec_name(SecEngineID, SecName1), + p("User: ~p", [User1]), + + p("lookup 2 (ok)"), + ?line {ok, #usm_user{name = UserName2} = User2} = + snmpm_config:get_usm_user_from_sec_name(SecEngineID, SecName2), + p("User: ~p", [User2]), + + p("lookup 3 (error)"), + ?line {error, not_found} = + snmpm_config:get_usm_user_from_sec_name(SecEngineID, SecName2 ++ "_1"), + + %% -- + p("stop config process"), + ?line ok = snmpm_config:stop(), + await_config_not_running(), + + %% -- + p("done"), + ok. +%% ?SKIP(not_yet_implemented). + + +%% +%% --- +%% + +register_usm_user_using_function(suite) -> []; +register_usm_user_using_function(doc) -> + "Register usm user using the API (function)."; +register_usm_user_using_function(Conf) when is_list(Conf) -> + put(tname,ruuufu), + p("start"), + process_flag(trap_exit, true), + + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + Opts = [{versions, [v3]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + %% -- + p("write manager config file"), + write_manager_conf(ConfDir), + + %% -- + p("start the config process"), + ?line {ok, _Pid} = config_start(Opts), + + %% -- + p("register usm user's"), + EngineID = "loctzp's engine", + + p("register user 1 (ok)"), + UserName1 = "samu_auth1", + SecName1 = UserName1, + UsmConfig1 = [{sec_name, SecName1}, + {auth, usmHMACMD5AuthProtocol}, + {auth_key, [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]}, + {priv, usmNoPrivProtocol}], + ?line ok = snmpm_config:register_usm_user(EngineID, UserName1, UsmConfig1), + p("try register user 1 again (error)"), + ?line {error, {already_registered, EngineID, UserName1}} = + snmpm_config:register_usm_user(EngineID, UserName1, UsmConfig1), + + p("register user 2 (ok)"), + UserName2 = "samu_auth2", + SecName2 = UserName2, + UsmConfig2 = [{auth, usmHMACMD5AuthProtocol}, + {auth_key, [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]}, + {priv, usmNoPrivProtocol}], + ?line ok = snmpm_config:register_usm_user(EngineID, UserName2, UsmConfig2), + + p("register user 3 (ok)"), + UserName3 = "samu3", + SecName3 = "samu_auth3", + UsmConfig3 = [{sec_name, SecName3}, + {auth, usmHMACMD5AuthProtocol}, + {auth_key, [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6]}, + {priv, usmNoPrivProtocol}], + ?line ok = snmpm_config:register_usm_user(EngineID, UserName3, UsmConfig3), + + p("lookup 1 (ok)"), + ?line {ok, #usm_user{name = UserName1} = User1} = + snmpm_config:get_usm_user_from_sec_name(EngineID, SecName1), + p("User: ~p", [User1]), + + p("lookup 2 (ok)"), + ?line {ok, #usm_user{name = UserName2} = User2} = + snmpm_config:get_usm_user_from_sec_name(EngineID, SecName2), + p("User: ~p", [User2]), + + p("lookup 3 (ok)"), + ?line {ok, #usm_user{name = UserName3} = User3} = + snmpm_config:get_usm_user_from_sec_name(EngineID, SecName3), + p("User: ~p", [User3]), + + p("lookup 4 (error)"), + ?line {error, not_found} = + snmpm_config:get_usm_user_from_sec_name(EngineID, SecName3 ++ "_1"), + + %% -- + p("stop config process"), + ?line ok = snmpm_config:stop(), + await_config_not_running(), + + %% -- + p("done"), + ok. +%% ?SKIP(not_yet_implemented). + + +%% +%% --- +%% + +register_usm_user_failed_using_function1(suite) -> []; +register_usm_user_failed_using_function1(doc) -> + "Register usm user failed using incorrect arguments to API (function)."; +register_usm_user_failed_using_function1(Conf) when is_list(Conf) -> + put(tname,ruufufu1), + p("start"), + process_flag(trap_exit, true), + + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + + _ConfDir = ?config(manager_conf_dir, Conf), + _DbDir = ?config(manager_db_dir, Conf), + ?SKIP(not_yet_implemented). + + +%% +%% --- +%% + +update_usm_user_info(suite) -> []; +update_usm_user_info(doc) -> + "Update usm user info."; +update_usm_user_info(Conf) when is_list(Conf) -> + put(tname,ruufufu1), + p("start"), + process_flag(trap_exit, true), + + case ?CRYPTO_START() of + ok -> + case ?CRYPTO_SUPPORT() of + {no, Reason} -> + ?SKIP({unsupported_encryption, Reason}); + yes -> + ok + end; + {error, Reason} -> + ?SKIP({failed_starting_crypto, Reason}) + end, + + _ConfDir = ?config(manager_conf_dir, Conf), + _DbDir = ?config(manager_db_dir, Conf), + ?SKIP(not_yet_implemented). + + +%% +%% --- +%% + +counter(doc) -> + "Various counter related operations with the snmp manager config"; +counter(suite) -> + [ + create_and_increment + ]. + + +%% +%% --- +%% + +create_and_increment(suite) -> []; +create_and_increment(doc) -> + "Craete and increment counters."; +create_and_increment(Conf) when is_list(Conf) -> + put(tname,cai), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{versions, [v1]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + ?line {ok, _Pid} = snmpm_config:start_link(Opts), + + %% Random init + {A,B,C} = erlang:now(), + random:seed(A,B,C), + + StartVal = random:uniform(2147483647), + IncVal = 42, + EndVal = StartVal + IncVal, + + ?line StartVal = snmpm_config:cre_counter(test_id, StartVal), + ?line EndVal = snmpm_config:incr_counter(test_id, IncVal), + + ?line ok = snmpm_config:stop(), + await_config_not_running(), + ok. + + +%% +%% --- +%% + +stats_counter(doc) -> + "Various statistic counter related operations with the " + "snmp manager config"; +stats_counter(suite) -> + [ + stats_create_and_increment + ]. + + +%% +%% --- +%% + +stats_create_and_increment(suite) -> []; +stats_create_and_increment(doc) -> + "Create and increment statistics counters."; +stats_create_and_increment(Conf) when is_list(Conf) -> + put(tname,scai), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{versions, [v1]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + ?line {ok, _Pid} = snmpm_config:start_link(Opts), + + p("stats table (1): ~p", [ets:tab2list(snmpm_stats_table)]), + ?line 0 = snmpm_config:maybe_cre_stats_counter(stats1, 0), + p("stats table (2): ~p", [ets:tab2list(snmpm_stats_table)]), + ?line ok = snmpm_config:maybe_cre_stats_counter(stats1, 0), + p("stats table (3): ~p", [ets:tab2list(snmpm_stats_table)]), + ?line 1 = snmpm_config:maybe_cre_stats_counter(stats2, 1), + p("stats table (4): ~p", [ets:tab2list(snmpm_stats_table)]), + ?line 10 = snmpm_config:cre_stats_counter(stats3, 10), + p("stats table (5): ~p", [ets:tab2list(snmpm_stats_table)]), + + Stats1Inc = fun() -> snmpm_config:incr_stats_counter(stats1, 1) end, + ?line 10 = loop(10, -1, Stats1Inc), + p("stats table (6): ~p", [ets:tab2list(snmpm_stats_table)]), + + ?line ok = snmpm_config:reset_stats_counter(stats1), + + ?line 10 = loop(10, -1, Stats1Inc), + + ?line ok = snmpm_config:stop(), + await_config_not_running(), + ok. + + +loop(0, Acc, _) -> + Acc; +loop(N, _, F) when (N > 0) andalso is_function(F) -> + Acc = F(), + loop(N-1, Acc, F). + + +%%====================================================================== +%% Ticket test-cases +%%====================================================================== + +tickets(suite) -> + [ + otp_7219 + ]. + + +otp_7219(suite) -> + []; +otp_7219(doc) -> + "Test-case for ticket OTP-7219"; +otp_7219(Config) when is_list(Config) -> + put(tname, otp7219), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + p("write manager configuration"), + write_manager_conf(ConfDir), + + Opts1 = [{versions, [v1]}, + {inform_request_behaviour, user}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("start manager config"), + ?line {ok, _Pid1} = snmpm_config:start_link(Opts1), + + p("get some manager config"), + {ok, {user, _}} = snmpm_config:system_info(net_if_irb), + + p("stop manager config"), + ?line ok = snmpm_config:stop(), + await_config_not_running(), + + IRB_TO = 15322, + Opts2 = [{versions, [v1]}, + {inform_request_behaviour, {user, IRB_TO}}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("start manager config"), + ?line {ok, _Pid2} = snmpm_config:start_link(Opts2), + + p("get some manager config"), + {ok, {user, IRB_TO}} = snmpm_config:system_info(net_if_irb), + + p("stop manager config"), + ?line ok = snmpm_config:stop(), + await_config_not_running(), + + p("done"), + ok. + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +await_config_not_running() -> + await_not_running(snmpm_config, 5). + +await_not_running(Name, 0) -> + p("await_not_running -> done waiting for ~w to die - try kill it", [Name]), + %% Ok, we tried it the nice way, now use brute force + await_killed(Name, 5); +await_not_running(Name, N) when N > 0 -> + p("await_not_running -> is process ~w still running (~w)", [Name, N]), + case erlang:whereis(Name) of + undefined -> + p("await_not_running -> no such (~w) process - sleep some",[Name]), + ?SLEEP(1000), + p("await_not_running -> no such (~w) process - done", [Name]), + ok; + Pid when is_pid(Pid) -> + p("~w process still running", [Name]), + ?SLEEP(500), + await_not_running(Name, N-1) + end. + +await_killed(Name, 0) -> + p("await_killed -> could not kill ~w => giving up", [Name]), + exit({error, {failed_terminating, Name}}); +await_killed(Name, N) when N > 0 -> + p("await_killed -> is process ~w still running (~w)", [Name, N]), + case whereis(Name) of + undefined -> + p("await_killed -> no such (~w) process - sleep some", [Name]), + ?SLEEP(1000), + p("await_killed -> no such (~w) process - done", [Name]), + ok; + Pid when is_pid(Pid) -> + p("await_killed -> ~w still running - try kill it", [Name]), + exit(Pid, kill), + ?SLEEP(1000), + await_killed(Name, N-1) + end. + + +config_start(Opts) -> + (catch snmpm_config:start_link(Opts)). + +config_stop() -> + (catch snmpm_config:stop()). + + +%% ------ + +join(Dir, File) -> + filename:join(Dir, File). + + +%% ------ + +write_manager_conf(Dir) -> + Port = "5000", + MMS = "484", + EngineID = "\"mgrEngine\"", + Str = lists:flatten( + io_lib:format("%% Minimum manager config file\n" + "{port, ~s}.\n" + "{max_message_size, ~s}.\n" + "{engine_id, ~s}.\n", + [Port, MMS, EngineID])), + write_manager_conf(Dir, Str). + +write_manager_conf(Dir, IP, Port, MMS, EngineID) -> + Str = lists:flatten( + io_lib:format("{address, ~s}.\n" + "{port, ~s}.\n" + "{max_message_size, ~s}.\n" + "{engine_id, ~s}.\n", + [IP, Port, MMS, EngineID])), + write_manager_conf(Dir, Str). + +write_manager_conf(Dir, Str) -> + write_conf_file(Dir, "manager.conf", Str). + + +write_users_conf(Dir, Users) -> + F = fun({UserId, UserMod, UserData}) -> %% Old format + lists:flatten( + io_lib:format("{~s, ~s, ~s, ~s}.~n", + [UserId, UserMod, UserData, "[]"])); + ({UserId, UserMod, UserData, DefaultAgentConfig}) -> %% New format + lists:flatten( + io_lib:format("{~s, ~s, ~s, ~s}.~n", + [UserId, UserMod, UserData, DefaultAgentConfig])) + end, + Str = lists:flatten([F(User) || User <- Users]), + write_conf_file(Dir, "users.conf", Str). + +write_users_conf2(Dir, Str) -> + write_conf_file(Dir, "users.conf", Str). + + +write_agents_conf(Dir, Agents) -> + F = fun({UserId, + TargetName, Comm, + Ip, Port, EngineID, + Timeout, MMS, + Version, SecModel, SecName, SecLevel}) -> + lists:flatten( + io_lib:format("{~s, ~n" + " ~s, ~s, ~n" + " ~s, ~s, ~s, ~n" + " ~s, ~s, ~n" + " ~s, ~s, ~s, ~s}.~n", + [UserId, + TargetName, Comm, + Ip, Port, EngineID, + Timeout, MMS, + Version, SecModel, SecName, SecLevel])) + end, + Str = lists:flatten([F(Agent) || Agent <- Agents]), + write_conf_file(Dir, "agents.conf", Str). + +write_agents_conf2(Dir, Str) -> + write_conf_file(Dir, "agents.conf", Str). + + +write_usm_conf(Dir, Usms) -> + F = fun({EngineID, UserName, SecName, AuthP, AuthKey, PrivP, PrivKey}) -> + lists:flatten( + io_lib:format("{~s, ~s, ~s, ~n" + " ~s, ~s, ~n" + " ~s, ~s}.~n", + [EngineID, UserName, SecName, + AuthP, AuthKey, + PrivP, PrivKey])); + ({EngineID, UserName, AuthP, AuthKey, PrivP, PrivKey}) -> + lists:flatten( + io_lib:format("{~s, ~s, ~n" + " ~s, ~s, ~n" + " ~s, ~s}.~n", + [EngineID, UserName, + AuthP, AuthKey, + PrivP, PrivKey])); + (Usm) -> + exit({invalid_usm, Usm}) + end, + Str = lists:flatten([F(Usm) || Usm <- Usms]), + write_conf_file(Dir, "usm.conf", Str). + +write_usm_conf2(Dir, Str) -> + write_conf_file(Dir, "usm.conf", Str). + + +write_conf_file(Dir, File, Str) -> + ?line {ok, Fd} = file:open(filename:join(Dir, File), write), + ?line ok = io:format(Fd, "~s", [Str]), + file:close(Fd). + + +%% ------ + +str(X) -> + lists:flatten(io_lib:format("~w", [X])). + + +%% ------ + +p(F) -> + p(F, []). + +p(F, A) -> + p(get(tname), F, A). + +p(TName, F, A) -> + io:format("*** [~s] ***" + " ~w -> " ++ F ++ "~n", [format_timestamp(now()),TName|A]). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl new file mode 100644 index 0000000000..31cc095349 --- /dev/null +++ b/lib/snmp/test/snmp_manager_test.erl @@ -0,0 +1,5436 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: +%% +%% Test: ts:run(snmp, snmp_manager_test, [batch]). +%% Test: ts:run(snmp, snmp_manager_test, event_tests, [batch]). +%% Test: ts:run(snmp, snmp_manager_test, inform_swarm, [batch]). +%% +%%---------------------------------------------------------------------- +-module(snmp_manager_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- + +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-include("snmp_test_data/Test2.hrl"). + +-include_lib("snmp/include/snmp_types.hrl"). +-include_lib("snmp/include/STANDARD-MIB.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + all/1, + init_per_testcase/2, fin_per_testcase/2, + + start_and_stop_tests/1, + simple_start_and_stop1/1, + simple_start_and_stop2/1, + simple_start_and_monitor_crash1/1, + simple_start_and_monitor_crash2/1, + notify_started01/1, + notify_started02/1, + + user_tests/1, + register_user1/1, + + agent_tests/1, + register_agent1/1, + register_agent2/1, + + misc_tests/1, + info/1, + + request_tests/1, + + get_tests/1, + simple_sync_get1/1, + simple_sync_get2/1, + simple_async_get1/1, + simple_async_get2/1, + + get_next_tests/1, + simple_sync_get_next1/1, + simple_sync_get_next2/1, + simple_async_get_next1/1, + simple_async_get_next2/1, + + set_tests/1, + simple_sync_set1/1, + simple_sync_set2/1, + simple_async_set1/1, + simple_async_set2/1, + + bulk_tests/1, + simple_sync_get_bulk1/1, + simple_sync_get_bulk2/1, + simple_async_get_bulk1/1, + simple_async_get_bulk2/1, + + misc_request_tests/1, + misc_async1/1, + misc_async2/1, + + discovery/1, + + event_tests/1, + + trap1/1, + trap2/1, + + inform1/1, + inform2/1, + inform3/1, + inform4/1, + inform_swarm/1, + + report/1, + + tickets/1, + otp8015/1, + otp8015_1/1 + + ]). + + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- + +%% -export([async_exec/2]). + + +%%---------------------------------------------------------------------- +%% Macros and constants +%%---------------------------------------------------------------------- + +-define(AGENT_PORT, 4000). +-define(AGENT_MMS, 1024). +-define(AGENT_ENGINE_ID, "agentEngine"). + +-define(MGR_PORT, 5000). +-define(MGR_MMS, 1024). +-define(MGR_ENGINE_ID, "mgrEngine"). + +-define(NS_TIMEOUT, 10000). + + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(Case, Config) when is_list(Config) -> + io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE,Case]), + init_per_testcase2(Case, Config). + +init_per_testcase2(Case, Config) -> + ?DBG("init [~w] Nodes [1]: ~p", [Case, erlang:nodes()]), + + %% Fix a correct data dir (points to the wrong location): + DataDir0 = ?config(data_dir, Config), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + + PrivDir = ?config(priv_dir, Config), + + TopDir = filename:join(PrivDir, ?MODULE), + case file:make_dir(TopDir) of + ok -> + ok; + {error, eexist} -> + ok; + Error -> + ?FAIL({failed_creating_subsuite_top_dir, Error}) + end, + + CaseTopDir = filename:join(TopDir, Case), + ?line ok = file:make_dir(CaseTopDir), + + %% -- Manager dirs -- + MgrTopDir = filename:join(CaseTopDir, "manager/"), + ?line ok = file:make_dir(MgrTopDir), + + MgrConfDir = filename:join(MgrTopDir, "conf/"), + ?line ok = file:make_dir(MgrConfDir), + + MgrDbDir = filename:join(MgrTopDir, "db/"), + ?line ok = file:make_dir(MgrDbDir), + + MgrLogDir = filename:join(MgrTopDir, "log/"), + ?line ok = file:make_dir(MgrLogDir), + + %% -- Agent dirs -- + AgTopDir = filename:join(CaseTopDir, "agent/"), + ?line ok = file:make_dir(AgTopDir), + + AgConfDir = filename:join(AgTopDir, "conf/"), + ?line ok = file:make_dir(AgConfDir), + + AgDbDir = filename:join(AgTopDir, "db/"), + ?line ok = file:make_dir(AgDbDir), + + AgLogDir = filename:join(AgTopDir, "log/"), + ?line ok = file:make_dir(AgLogDir), + + Conf = [{snmp_data_dir, DataDir}, + {watchdog, ?WD_START(?MINS(5))}, + {ip, ?LOCALHOST()}, + {top_dir, TopDir}, + {agent_dir, AgTopDir}, + {agent_conf_dir, AgConfDir}, + {agent_db_dir, AgDbDir}, + {agent_log_dir, AgLogDir}, + {manager_agent_target_name, "agent01"}, + {manager_dir, MgrTopDir}, + {manager_conf_dir, MgrConfDir}, + {manager_db_dir, MgrDbDir}, + {manager_log_dir, MgrLogDir} | Config], + Conf2 = init_per_testcase3(Case, Conf), + ?DBG("init [~w] Nodes [2]: ~p", [Case, erlang:nodes()]), + Conf2. + +init_per_testcase3(Case, Config) -> + OldApiCases = + [ + simple_sync_get1, + simple_async_get1, + simple_sync_get_next1, + simple_async_get_next1, + simple_sync_set1, + simple_async_set1, + simple_sync_get_bulk1, + simple_async_get_bulk1, + misc_async1 + ], + NewApiCases = + [ + simple_sync_get2, + simple_async_get2, + simple_sync_get_next2, + simple_async_get_next2, + simple_sync_set2, + simple_async_set2, + simple_sync_get_bulk2, + simple_async_get_bulk2, + misc_async2 + ], + Cases = [ + trap1, + trap2, + inform1, + inform2, + inform3, + inform4, + inform_swarm, + report + ] ++ OldApiCases ++ NewApiCases, + case lists:member(Case, Cases) of + true -> + NoAutoInformCases = [inform1, inform2, inform3, inform_swarm], + AutoInform = not lists:member(Case, NoAutoInformCases), + Conf1 = if + Case =:= inform_swarm -> + Verb = [{manager_config_verbosity, silence}, + {manager_note_store_verbosity, silence}, + {manager_server_verbosity, info}, + {manager_net_if_verbosity, info}, + {agent_verbosity, info}, + {agent_net_if_verbosity, info}], + Verb ++ Config; + true -> + Config + end, + Conf2 = init_agent(Conf1), + Conf3 = init_manager(AutoInform, Conf2), + Conf4 = init_mgr_user(Conf3), + case lists:member(Case, NewApiCases) of + true -> + init_mgr_user_data2(Conf4); + false -> + init_mgr_user_data1(Conf4) + end; + false -> + Config + end. + +fin_per_testcase(Case, Config) when is_list(Config) -> + ?DBG("fin [~w] Nodes [1]: ~p", [Case, erlang:nodes()]), + Dog = ?config(watchdog, Config), + ?WD_STOP(Dog), + Conf1 = lists:keydelete(watchdog, 1, Config), + Conf2 = fin_per_testcase2(Case, Conf1), + ?DBG("fin [~w] Nodes [2]: ~p", [Case, erlang:nodes()]), + %% TopDir = ?config(top_dir, Conf2), + %% ?DEL_DIR(TopDir), + Conf2. + +fin_per_testcase2(Case, Config) -> + OldApiCases = + [ + simple_sync_get1, + simple_async_get1, + simple_sync_get_next1, + simple_async_get_next1, + simple_sync_set1, + simple_async_set1, + simple_sync_get_bulk1, + simple_async_get_bulk1, + misc_async1 + ], + NewApiCases = + [ + simple_sync_get2, + simple_async_get2, + simple_sync_get_next2, + simple_async_get_next2, + simple_sync_set2, + simple_async_set2, + simple_sync_get_bulk2, + simple_async_get_bulk2, + misc_async2 + ], + Cases = [ + trap1, + trap2, + inform1, + inform2, + inform3, + inform4, + inform_swarm, + report + ] ++ OldApiCases ++ NewApiCases, + case lists:member(Case, Cases) of + true -> + Conf1 = case lists:member(Case, NewApiCases) of + true -> + fin_mgr_user_data2(Config); + false -> + fin_mgr_user_data1(Config) + end, + Conf2 = fin_mgr_user(Conf1), + Conf3 = fin_manager(Conf2), + fin_agent(Conf3); + false -> + Config + end. + + +%%====================================================================== +%% Test case definitions +%%====================================================================== + +all(suite) -> + [ + start_and_stop_tests, + misc_tests, + user_tests, + agent_tests, + request_tests, + event_tests, + discovery, + tickets + ]. + +start_and_stop_tests(suite) -> + [ + simple_start_and_stop1, + simple_start_and_stop2, + simple_start_and_monitor_crash1, + simple_start_and_monitor_crash2, + notify_started01, + notify_started02 + ]. + +misc_tests(suite) -> + [ + info + ]. + +user_tests(suite) -> + [ + register_user1 + ]. + +agent_tests(suite) -> + [ + register_agent1, + register_agent2 + ]. + +request_tests(suite) -> + [ + get_tests, + get_next_tests, + set_tests, + bulk_tests, + misc_request_tests + ]. + +get_tests(suite) -> + [ + simple_sync_get1, + simple_sync_get2, + simple_async_get1, + simple_async_get2 + ]. + +get_next_tests(suite) -> + [ + simple_sync_get_next1, + simple_sync_get_next2, + simple_async_get_next1, + simple_async_get_next2 + ]. + +set_tests(suite) -> + [ + simple_sync_set1, + simple_sync_set2, + simple_async_set1, + simple_async_set2 + ]. + +bulk_tests(suite) -> + [ + simple_sync_get_bulk1, + simple_sync_get_bulk2, + simple_async_get_bulk1, + simple_async_get_bulk2 + ]. + +misc_request_tests(suite) -> + [ + misc_async1, + misc_async2 + ]. + +event_tests(suite) -> + [ + trap1, + trap2, + inform1, + inform2, + inform3, + inform4, + inform_swarm, + report + ]. + +tickets(suite) -> + [ + otp8015 + ]. + +otp8015(suite) -> + [ + otp8015_1 + ]. + + +%%====================================================================== +%% Test functions +%%====================================================================== + +simple_start_and_stop1(suite) -> []; +simple_start_and_stop1(Config) when is_list(Config) -> + %% ?SKIP(not_yet_implemented), + process_flag(trap_exit, true), + put(tname,ssas1), + p("starting with Config: ~n~p", [Config]), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + p("manager started, now try to stop"), + ok = snmpm:stop(), + + ?SLEEP(1000), + + p("end"), + ok. + + +%%====================================================================== + +simple_start_and_stop2(suite) -> []; +simple_start_and_stop2(Config) when is_list(Config) -> + %% ?SKIP(not_yet_implemented), + process_flag(trap_exit, true), + put(tname,ssas2), + p("starting with Config: ~p~n", [Config]), + + ManagerNode = start_manager_node(), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + + p("try load snmp application"), + ?line ok = load_snmp(ManagerNode), + + p("try set manager env for the snmp application"), + ?line ok = set_mgr_env(ManagerNode, Opts), + + p("try starting snmp application (with only manager)"), + ?line ok = start_snmp(ManagerNode), + + p("started"), + + ?SLEEP(1000), + + p("try stopping snmp application (with only manager)"), + ?line ok = stop_snmp(ManagerNode), + + ?SLEEP(1000), + + stop_node(ManagerNode), + + ?SLEEP(1000), + + p("end"), + ok. + + +%%====================================================================== + +simple_start_and_monitor_crash1(suite) -> []; +simple_start_and_monitor_crash1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,ssamc1), + p("starting with Config: ~n~p", [Config]), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start(Opts), + + ?SLEEP(1000), + + p("create the monitor"), + Ref = snmpm:monitor(), + + p("make sure it has not already crashed..."), + receive + {'DOWN', Ref, process, Obj1, Reason1} -> + ?FAIL({unexpected_down, Obj1, Reason1}) + after 1000 -> + ok + end, + + p("stop the manager"), + ok = snmpm:stop(), + + p("await the down-message"), + receive + {'DOWN', Ref, process, Obj2, Reason2} -> + p("received expected down-message: " + "~n Obj2: ~p" + "~n Reason2: ~p", + [Obj2, Reason2]), + ok + after 1000 -> + ?FAIL(timeout) + end, + + p("end"), + ok. + + +%%====================================================================== + +simple_start_and_monitor_crash2(suite) -> []; +simple_start_and_monitor_crash2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,ssamc2), + p("starting with Config: ~n~p", [Config]), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{restart_type, permanent}, + {server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start(Opts), + + ?SLEEP(1000), + + p("create the monitor"), + Ref = snmpm:monitor(), + + p("make sure it has not already crashed..."), + receive + {'DOWN', Ref, process, Obj1, Reason1} -> + ?FAIL({unexpected_down, Obj1, Reason1}) + after 1000 -> + ok + end, + + p("crash the manager"), + simulate_crash(), + + p("await the down-message"), + receive + {'DOWN', Ref, process, Obj2, Reason2} -> + p("received expected down-message: " + "~n Obj2: ~p" + "~n Reason2: ~p", + [Obj2, Reason2]), + ok + after 1000 -> + ?FAIL(timeout) + end, + + p("end"), + ok. + + +%% The server supervisor allow 5 restarts in 500 msec. +server_pid() -> + whereis(snmpm_server). + +-define(MAX_KILLS, 6). + +simulate_crash() -> + simulate_crash(0, server_pid()). + +simulate_crash(?MAX_KILLS, _) -> + ?SLEEP(1000), + case server_pid() of + P when is_pid(P) -> + exit({error, {still_alive, P}}); + _ -> + ok + end; +simulate_crash(NumKills, Pid) when (NumKills < ?MAX_KILLS) and is_pid(Pid) -> + p("similate_crash -> ~w, ~p", [NumKills, Pid]), + Ref = erlang:monitor(process, Pid), + exit(Pid, kill), + receive + {'DOWN', Ref, process, _Object, _Info} -> + p("received expected 'DOWN' message"), + simulate_crash(NumKills + 1, server_pid()) + after 1000 -> + case server_pid() of + P when is_pid(P) -> + exit({error, {no_down_from_server, P}}); + _ -> + ok + end + end; +simulate_crash(NumKills, _) -> + ?SLEEP(10), + simulate_crash(NumKills, server_pid()). + + +%%====================================================================== + +notify_started01(suite) -> []; +notify_started01(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,ns01), + p("starting with Config: ~n~p", [Config]), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, log}]}, + {net_if, [{verbosity, silence}]}, + {note_store, [{verbosity, silence}]}, + {config, [{verbosity, log}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("request start notification (1)"), + Pid1 = snmpm:notify_started(10000), + receive + {snmpm_start_timeout, Pid1} -> + p("received expected start timeout"), + ok; + Any1 -> + ?FAIL({unexpected_message, Any1}) + after 15000 -> + ?FAIL({unexpected_timeout, Pid1}) + end, + + p("request start notification (2)"), + Pid2 = snmpm:notify_started(10000), + + p("start the snmpm starter"), + Pid = snmpm_starter(Opts, 5000), + + p("await the start notification"), + Ref = + receive + {snmpm_started, Pid2} -> + p("received started message -> create the monitor"), + snmpm:monitor(); + Any2 -> + ?FAIL({unexpected_message, Any2}) + after 15000 -> + ?FAIL({unexpected_timeout, Pid2}) + end, + + p("[~p] make sure it has not already crashed...", [Ref]), + receive + {'DOWN', Ref, process, Obj1, Reason1} -> + ?FAIL({unexpected_down, Obj1, Reason1}) + after 1000 -> + ok + end, + + p("stop the manager"), + Pid ! {stop, self()}, %ok = snmpm:stop(), + + p("await the down-message"), + receive + {'DOWN', Ref, process, Obj2, Reason2} -> + p("received expected down-message: " + "~n Obj2: ~p" + "~n Reason2: ~p", + [Obj2, Reason2]), + ok + after 5000 -> + ?FAIL(down_timeout) + end, + + p("end"), + ok. + + +snmpm_starter(Opts, To) -> + Parent = self(), + spawn( + fun() -> + ?SLEEP(To), + ok = snmpm:start(Opts), + receive + {stop, Parent} -> + snmpm:stop() + end + end). + + +%%====================================================================== + +notify_started02(suite) -> []; +notify_started02(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,ns02), + p("starting with Config: ~n~p", [Config]), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, log}]}, + {net_if, [{verbosity, silence}]}, + {note_store, [{verbosity, silence}]}, + {config, [{verbosity, log}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("start snmpm client process"), + Pid1 = ns02_loop1_start(), + + p("start snmpm starter process"), + Pid2 = ns02_loop2_start(Opts), + + p("await snmpm client process exit"), + receive + {'EXIT', Pid1, normal} -> + ok; + {'EXIT', Pid1, Reason1} -> + ?FAIL(Reason1) + after 25000 -> + ?FAIL(timeout) + end, + + p("await snmpm starter process exit"), + receive + {'EXIT', Pid2, normal} -> + ok; + {'EXIT', Pid2, Reason2} -> + ?FAIL(Reason2) + after 5000 -> + ?FAIL(timeout) + end, + + p("end"), + ok. + + +ns02_loop1_start() -> + spawn_link(fun() -> ns02_loop1() end). + +ns02_loop1() -> + put(tname,ns02_loop1), + p("starting"), + ns02_loop1(dummy, snmpm:notify_started(?NS_TIMEOUT), 5). + +ns02_loop1(_Ref, _Pid, 0) -> + p("done"), + exit(normal); +ns02_loop1(Ref, Pid, N) -> + p("entry when" + "~n Ref: ~p" + "~n Pid: ~p" + "~n N: ~p", [Ref, Pid, N]), + receive + {snmpm_started, Pid} -> + p("received expected started message (~w)", [N]), + ns02_loop1(snmpm:monitor(), dummy, N); + {snmpm_start_timeout, Pid} -> + p("unexpected timout"), + ?FAIL({unexpected_start_timeout, Pid}); + {'DOWN', Ref, process, Obj, Reason} -> + p("received expected DOWN message (~w) with" + "~n Obj: ~p" + "~n Reason: ~p", [N, Obj, Reason]), + ns02_loop1(dummy, snmpm:notify_started(?NS_TIMEOUT), N-1) + after 10000 -> + ?FAIL(timeout) + end. + + +ns02_loop2_start(Opts) -> + spawn_link(fun() -> ns02_loop2(Opts) end). + +ns02_loop2(Opts) -> + put(tname,ns02_loop2), + p("starting"), + ns02_loop2(Opts, 5). + +ns02_loop2(_Opts, 0) -> + p("done"), + exit(normal); +ns02_loop2(Opts, N) -> + p("entry when N: ~p", [N]), + ?SLEEP(2000), + p("start manager"), + snmpm:start(Opts), + ?SLEEP(2000), + p("stop manager"), + snmpm:stop(), + ns02_loop2(Opts, N-1). + + +%%====================================================================== + +info(suite) -> []; +info(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,info), + p("starting with Config: ~n~p", [Config]), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start(Opts), + + ?SLEEP(1000), + + p("manager started, now get info"), + Info = snmpm:info(), + p("got info, now verify: ~n~p", [Info]), + ok = verify_info( Info ), + + p("info verified, now try to stop"), + ok = snmpm:stop(), + + ?SLEEP(1000), + + p("end"), + ok. + +verify_info(Info) when is_list(Info) -> + Keys = [{server, [process_memory, db_memory]}, + {config, [process_memory, db_memory]}, + {net_if, [process_memory, port_info]}, + {note_store, [process_memory, db_memory]}, + stats_counters], + verify_info(Keys, Info); +verify_info(BadInfo) -> + {error, {bad_info, BadInfo}}. + +verify_info([], _) -> + ok; +verify_info([Key|Keys], Info) when is_atom(Key) -> + case lists:keymember(Key, 1, Info) of + true -> + verify_info(Keys, Info); + false -> + {error, {missing_info, {Key, Info}}} + end; +verify_info([{Key, SubKeys}|Keys], Info) -> + case lists:keysearch(Key, 1, Info) of + {value, {Key, SubInfo}} -> + case verify_info(SubKeys, SubInfo) of + ok -> + verify_info(Keys, Info); + {error, {missing_info, {SubKey, _}}} -> + {error, {missing_subinfo, {Key, SubKey, Info}}} + end; + false -> + {error, {missing_info, {Key, Info}}} + end. + + +%%====================================================================== + +register_user1(suite) -> []; +register_user1(Config) when is_list(Config) -> + %% ?SKIP(not_yet_implemented). + process_flag(trap_exit, true), + put(tname,ru1), + p("starting with Config: ~p~n", [Config]), + + ManagerNode = start_manager_node(), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + + p("load snmp application"), + ?line ok = load_snmp(ManagerNode), + + p("set manager env for the snmp application"), + ?line ok = set_mgr_env(ManagerNode, Opts), + + p("starting snmp application (with only manager)"), + ?line ok = start_snmp(ManagerNode), + + p("started"), + + ?SLEEP(1000), + + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("try register user(s)"), + ?line ok = mgr_register_user(ManagerNode, calvin, snmpm_user_default, + [self(), "various misc info"]), + + Users1 = mgr_which_users(ManagerNode), + p("users: ~p~n", [Users1]), + ?line ok = verify_users(Users1, [calvin]), + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + ?line ok = mgr_register_user(ManagerNode, hobbe, snmpm_user_default, + {"misc info", self()}), + + Users2 = mgr_which_users(ManagerNode), + p("users: ~p~n", [Users2]), + ?line ok = verify_users(Users2, [calvin, hobbe]), + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("try unregister user(s)"), + ?line ok = mgr_unregister_user(ManagerNode, calvin), + + Users3 = mgr_which_users(ManagerNode), + p("users: ~p~n", [Users3]), + ?line ok = verify_users(Users3, [hobbe]), + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + ?line ok = mgr_unregister_user(ManagerNode, hobbe), + + Users4 = mgr_which_users(ManagerNode), + p("users: ~p~n", [Users4]), + ?line ok = verify_users(Users4, []), + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + ?SLEEP(1000), + + p("stop snmp application (with only manager)"), + ?line ok = stop_snmp(ManagerNode), + + ?SLEEP(1000), + + stop_node(ManagerNode), + + ?SLEEP(1000), + + p("end"), + ok. + +verify_users([], []) -> + ok; +verify_users(ActualUsers, []) -> + {error, {unexpected_users, ActualUsers}}; +verify_users(ActualUsers0, [User|RegUsers]) -> + case lists:delete(User, ActualUsers0) of + ActualUsers0 -> + {error, {not_registered, User}}; + ActualUsers -> + verify_users(ActualUsers, RegUsers) + end. + + +%%====================================================================== + +register_agent1(doc) -> + ["Test registration of agents with the OLD interface functions"]; +register_agent1(suite) -> + []; +register_agent1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,ra1), + p("starting with Config: ~p~n", [Config]), + + ManagerNode = start_manager_node(), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + + p("load snmp application"), + ?line ok = load_snmp(ManagerNode), + + p("set manager env for the snmp application"), + ?line ok = set_mgr_env(ManagerNode, Opts), + + p("starting snmp application (with only manager)"), + ?line ok = start_snmp(ManagerNode), + + p("started"), + + ?SLEEP(1000), + + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("register user(s) calvin & hobbe"), + ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []), + ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []), + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("register agent(s)"), + ?line ok = mgr_register_agent(ManagerNode, user_alfa, 5000, []), + ?line ok = mgr_register_agent(ManagerNode, user_alfa, 5001, []), + ?line ok = mgr_register_agent(ManagerNode, user_beta, 5002, []), + ?line ok = mgr_register_agent(ManagerNode, user_beta, 5003, []), + + p("verify all agent(s): expect 4"), + case mgr_which_agents(ManagerNode) of + Agents1 when length(Agents1) =:= 4 -> + p("all agents: ~p~n", [Agents1]), + ok; + Agents1 -> + ?FAIL({agent_registration_failure, Agents1}) + end, + + p("verify user_alfa agent(s)"), + case mgr_which_agents(ManagerNode, user_alfa) of + Agents2 when length(Agents2) =:= 2 -> + p("calvin agents: ~p~n", [Agents2]), + ok; + Agents2 -> + ?FAIL({agent_registration_failure, Agents2}) + end, + + p("verify user_beta agent(s)"), + case mgr_which_agents(ManagerNode, user_beta) of + Agents3 when length(Agents3) =:= 2 -> + p("hobbe agents: ~p~n", [Agents3]), + ok; + Agents3 -> + ?FAIL({agent_registration_failure, Agents3}) + end, + + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("unregister user user_alfa"), + ?line ok = mgr_unregister_user(ManagerNode, user_alfa), + + p("verify all agent(s): expect 2"), + case mgr_which_agents(ManagerNode) of + Agents4 when length(Agents4) =:= 2 -> + p("all agents: ~p~n", [Agents4]), + ok; + Agents4 -> + ?FAIL({agent_unregistration_failure, Agents4}) + end, + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("unregister user_beta agents"), + ?line ok = mgr_unregister_agent(ManagerNode, user_beta, 5002), + ?line ok = mgr_unregister_agent(ManagerNode, user_beta, 5003), + + p("verify all agent(s): expect 0"), + case mgr_which_agents(ManagerNode) of + [] -> + ok; + Agents5 -> + p("all agents: ~p~n", [Agents5]), + ?FAIL({agent_unregistration_failure, Agents5}) + end, + + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("unregister user hobbe"), + ?line ok = mgr_unregister_user(ManagerNode, user_beta), + + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + ?SLEEP(1000), + + p("stop snmp application (with only manager)"), + ?line ok = stop_snmp(ManagerNode), + + ?SLEEP(1000), + + stop_node(ManagerNode), + + ?SLEEP(1000), + + p("end"), + ok. + + +%%====================================================================== + +register_agent2(doc) -> + ["Test registration of agents with the NEW interface functions"]; +register_agent2(suite) -> + []; +register_agent2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ra2), + p("starting with Config: ~p~n", [Config]), + + ManagerNode = start_manager_node(), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + LocalHost = snmp_test_lib:localhost(), + + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + + p("load snmp application"), + ?line ok = load_snmp(ManagerNode), + + p("set manager env for the snmp application"), + ?line ok = set_mgr_env(ManagerNode, Opts), + + p("starting snmp application (with only manager)"), + ?line ok = start_snmp(ManagerNode), + + p("started"), + + ?SLEEP(1000), + + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("register user(s) calvin & hobbe"), + ?line ok = mgr_register_user(ManagerNode, user_alfa, snmpm_user_default, []), + ?line ok = mgr_register_user(ManagerNode, user_beta, snmpm_user_default, []), + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("register agent(s)"), + TargetName1 = "agent1", + ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName1, + [{address, LocalHost}, + {port, 5001}, + {engine_id, "agentEngineId-1"}]), + TargetName2 = "agent2", + ?line ok = mgr_register_agent(ManagerNode, user_alfa, TargetName2, + [{address, LocalHost}, + {port, 5002}, + {engine_id, "agentEngineId-2"}]), + TargetName3 = "agent3", + ?line ok = mgr_register_agent(ManagerNode, user_beta, TargetName3, + [{address, LocalHost}, + {port, 5003}, + {engine_id, "agentEngineId-3"}]), + TargetName4 = "agent4", + ?line ok = mgr_register_agent(ManagerNode, user_beta, TargetName4, + [{address, LocalHost}, + {port, 5004}, + {engine_id, "agentEngineId-4"}]), + + p("verify all agent(s): expect 4"), + case mgr_which_agents(ManagerNode) of + Agents1 when length(Agents1) =:= 4 -> + p("all agents: ~p~n", [Agents1]), + ok; + Agents1 -> + ?FAIL({agent_registration_failure, Agents1}) + end, + + p("verify user_alfa agent(s)"), + case mgr_which_agents(ManagerNode, user_alfa) of + Agents2 when length(Agents2) =:= 2 -> + p("calvin agents: ~p~n", [Agents2]), + ok; + Agents2 -> + ?FAIL({agent_registration_failure, Agents2}) + end, + + p("verify user_beta agent(s)"), + case mgr_which_agents(ManagerNode, user_beta) of + Agents3 when length(Agents3) =:= 2 -> + p("hobbe agents: ~p~n", [Agents3]), + ok; + Agents3 -> + ?FAIL({agent_registration_failure, Agents3}) + end, + + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("unregister user user_alfa"), + ?line ok = mgr_unregister_user(ManagerNode, user_alfa), + + p("verify all agent(s): expect 2"), + case mgr_which_agents(ManagerNode) of + Agents4 when length(Agents4) =:= 2 -> + p("all agents: ~p~n", [Agents4]), + ok; + Agents4 -> + ?FAIL({agent_unregistration_failure, Agents4}) + end, + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("unregister user_beta agents"), + ?line ok = mgr_unregister_agent(ManagerNode, user_beta, TargetName3), + ?line ok = mgr_unregister_agent(ManagerNode, user_beta, TargetName4), + + p("verify all agent(s): expect 0"), + case mgr_which_agents(ManagerNode) of + [] -> + ok; + Agents5 -> + p("all agents: ~p~n", [Agents5]), + ?FAIL({agent_unregistration_failure, Agents5}) + end, + + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + p("unregister user hobbe"), + ?line ok = mgr_unregister_user(ManagerNode, user_beta), + + p("manager info: ~p~n", [mgr_info(ManagerNode)]), + + ?SLEEP(1000), + + p("stop snmp application (with only manager)"), + ?line ok = stop_snmp(ManagerNode), + + ?SLEEP(1000), + + stop_node(ManagerNode), + + ?SLEEP(1000), + + p("end"), + ok. + + +%%====================================================================== + +simple_sync_get1(doc) -> ["Simple sync get-request - Old style (Addr & Port)"]; +simple_sync_get1(suite) -> []; +simple_sync_get1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ssg1), + p("starting with Config: ~p~n", [Config]), + + Node = ?config(manager_node, Config), + Addr = ?config(ip, Config), + Port = ?AGENT_PORT, + + p("issue get-request without loading the mib"), + Oids1 = [?sysObjectID_instance, ?sysDescr_instance, ?sysUpTime_instance], + ?line ok = do_simple_get(Node, Addr, Port, Oids1), + + p("issue get-request after first loading the mibs"), + ?line ok = mgr_user_load_mib(Node, std_mib()), + Oids2 = [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]], + ?line ok = do_simple_get(Node, Addr, Port, Oids2), + ok. + +do_simple_get(Node, Addr, Port, Oids) -> + ?line {ok, Reply, Rem} = mgr_user_sync_get(Node, Addr, Port, Oids), + + ?DBG("~n Reply: ~p" + "~n Rem: ~w", [Reply, Rem]), + + %% verify that the operation actually worked: + %% The order should be the same, so no need to seach + ?line ok = case Reply of + {noError, 0, [#varbind{oid = ?sysObjectID_instance, + value = SysObjectID}, + #varbind{oid = ?sysDescr_instance, + value = SysDescr}, + #varbind{oid = ?sysUpTime_instance, + value = SysUpTime}]} -> + p("expected result from get: " + "~n SysObjectID: ~p" + "~n SysDescr: ~s" + "~n SysUpTime: ~w", + [SysObjectID, SysDescr, SysUpTime]), + ok; + {noError, 0, Vbs} -> + p("unexpected varbinds: ~n~p", [Vbs]), + {error, {unexpected_vbs, Vbs}}; + Else -> + p("unexpected reply: ~n~p", [Else]), + {error, {unexpected_response, Else}} + end, + ok. + + +%%====================================================================== + +simple_sync_get2(doc) -> ["Simple sync get-request - New style (TargetName)"]; +simple_sync_get2(suite) -> []; +simple_sync_get2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ssg2), + p("starting with Config: ~p~n", [Config]), + + Node = ?config(manager_node, Config), + TargetName = ?config(manager_agent_target_name, Config), + + p("issue get-request without loading the mib"), + Oids1 = [?sysObjectID_instance, ?sysDescr_instance, ?sysUpTime_instance], + ?line ok = do_simple_get(Node, TargetName, Oids1), + + p("issue get-request after first loading the mibs"), + ?line ok = mgr_user_load_mib(Node, std_mib()), + Oids2 = [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]], + ?line ok = do_simple_get(Node, TargetName, Oids2), + ok. + +do_simple_get(Node, TargetName, Oids) -> + ?line {ok, Reply, Rem} = mgr_user_sync_get(Node, TargetName, Oids), + + ?DBG("~n Reply: ~p" + "~n Rem: ~w", [Reply, Rem]), + + %% verify that the operation actually worked: + %% The order should be the same, so no need to seach + ?line ok = case Reply of + {noError, 0, [#varbind{oid = ?sysObjectID_instance, + value = SysObjectID}, + #varbind{oid = ?sysDescr_instance, + value = SysDescr}, + #varbind{oid = ?sysUpTime_instance, + value = SysUpTime}]} -> + p("expected result from get: " + "~n SysObjectID: ~p" + "~n SysDescr: ~s" + "~n SysUpTime: ~w", + [SysObjectID, SysDescr, SysUpTime]), + ok; + {noError, 0, Vbs} -> + p("unexpected varbinds: ~n~p", [Vbs]), + {error, {unexpected_vbs, Vbs}}; + Else -> + p("unexpected reply: ~n~p", [Else]), + {error, {unexpected_response, Else}} + end, + ok. + + +%%====================================================================== + +simple_async_get1(doc) -> ["Simple (async) get-request - " + "Old style (Addr & Port)"]; +simple_async_get1(suite) -> []; +simple_async_get1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, sag1), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + Addr = ?config(ip, Config), + Port = ?AGENT_PORT, + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + Exec = fun(Data) -> + async_g_exec1(MgrNode, Addr, Port, Data) + end, + + Requests = [ + { 1, + [?sysObjectID_instance], + Exec, + fun(X) -> sag_verify(X, [?sysObjectID_instance]) end}, + { 2, + [?sysDescr_instance, ?sysUpTime_instance], + Exec, + fun(X) -> + sag_verify(X, [?sysObjectID_instance, + ?sysUpTime_instance]) + end}, + { 3, + [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]], + Exec, + fun(X) -> + sag_verify(X, [?sysObjectID_instance, + ?sysDescr_instance, + ?sysUpTime_instance]) + end}, + { 4, + [?sysObjectID_instance, + ?sysDescr_instance, + ?sysUpTime_instance], + Exec, + fun(X) -> + sag_verify(X, [?sysObjectID_instance, + ?sysDescr_instance, + ?sysUpTime_instance]) + end} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + +async_g_exec1(Node, Addr, Port, Oids) -> + mgr_user_async_get(Node, Addr, Port, Oids). + +sag_verify({noError, 0, _Vbs}, any) -> + p("verified [any]"), + ok; +sag_verify({noError, 0, Vbs}, Exp) -> + ?DBG("verified first stage ok: " + "~n Vbs: ~p" + "~n Exp: ~p", [Vbs, Exp]), + sag_verify_vbs(Vbs, Exp); +sag_verify(Error, _) -> + {error, {unexpected_response, Error}}. + +sag_verify_vbs([], []) -> + ?DBG("verified second stage ok", []), + ok; +sag_verify_vbs(Vbs, []) -> + {error, {unexpected_vbs, Vbs}}; +sag_verify_vbs([], Exp) -> + {error, {expected_vbs, Exp}}; +sag_verify_vbs([#varbind{oid = Oid}|Vbs], [any|Exp]) -> + p("verified [any] oid ~w", [Oid]), + sag_verify_vbs(Vbs, Exp); +sag_verify_vbs([#varbind{oid = Oid, value = Value}|Vbs], [Oid|Exp]) -> + p("verified oid ~w [~p]", [Oid, Value]), + sag_verify_vbs(Vbs, Exp); +sag_verify_vbs([#varbind{oid = Oid, value = Value}|Vbs], [{Oid,Value}|Exp]) -> + p("verified oid ~w and ~p", [Oid, Value]), + sag_verify_vbs(Vbs, Exp); +sag_verify_vbs([Vb|_], [E|_]) -> + {error, {unexpected_vb, Vb, E}}. + + +%%====================================================================== + +simple_async_get2(doc) -> ["Simple (async) get-request - " + "New style (TargetName)"]; +simple_async_get2(suite) -> []; +simple_async_get2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, sag2), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + TargetName = ?config(manager_agent_target_name, Config), + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + Exec = fun(Data) -> + async_g_exec2(MgrNode, TargetName, Data) + end, + + Requests = [ + { 1, + [?sysObjectID_instance], + Exec, + fun(X) -> sag_verify(X, [?sysObjectID_instance]) end}, + { 2, + [?sysDescr_instance, ?sysUpTime_instance], + Exec, + fun(X) -> + sag_verify(X, [?sysObjectID_instance, + ?sysUpTime_instance]) + end}, + { 3, + [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]], + Exec, + fun(X) -> + sag_verify(X, [?sysObjectID_instance, + ?sysDescr_instance, + ?sysUpTime_instance]) + end}, + { 4, + [?sysObjectID_instance, + ?sysDescr_instance, + ?sysUpTime_instance], + Exec, + fun(X) -> + sag_verify(X, [?sysObjectID_instance, + ?sysDescr_instance, + ?sysUpTime_instance]) + end} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + +async_g_exec2(Node, TargetName, Oids) -> + mgr_user_async_get(Node, TargetName, Oids). + + +%%====================================================================== + +simple_sync_get_next1(doc) -> ["Simple (sync) get_next-request - " + "Old style (Addr & Port)"]; +simple_sync_get_next1(suite) -> []; +simple_sync_get_next1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ssgn1), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + Addr = ?config(ip, Config), + Port = ?AGENT_PORT, + + %% -- 1 -- + Oids01 = [[1,3,7,1]], + VF01 = fun(X) -> verify_ssgn_reply1(X, [{[1,3,7,1],endOfMibView}]) end, + ?line ok = do_simple_get_next(1, + MgrNode, Addr, Port, Oids01, VF01), + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + + %% -- 2 -- + Oids02 = [[sysDescr], [1,3,7,1]], + VF02 = fun(X) -> + verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView]) + end, + ?line ok = do_simple_get_next(2, + MgrNode, Addr, Port, Oids02, VF02), + + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + %% -- 3 -- + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + Oids03 = [[TCnt2, 1]], + VF03 = fun(X) -> + verify_ssgn_reply1(X, [{fl([TCnt2,2]), 100}]) + end, + ?line ok = do_simple_get_next(3, + MgrNode, Addr, Port, Oids03, VF03), + + %% -- 4 -- + Oids04 = [[TCnt2, 2]], + VF04 = fun(X) -> + verify_ssgn_reply1(X, [{fl([TCnt2,2]), endOfMibView}]) + end, + ?line ok = do_simple_get_next(4, + MgrNode, Addr, Port, Oids04, VF04), + + %% -- 5 -- + ?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1), + Oids05 = [TGenErr1], + VF05 = fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]}) + end, + ?line ok = do_simple_get_next(5, + MgrNode, Addr, Port, Oids05, VF05), + + %% -- 6 -- + ?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2), + Oids06 = [TGenErr2], + VF06 = fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]}) + end, + ?line ok = do_simple_get_next(6, + MgrNode, Addr, Port, Oids06, VF06), + + %% -- 7 -- + ?line {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3), + Oids07 = [[sysDescr], TGenErr3], + VF07 = fun(X) -> + verify_ssgn_reply2(X, {genErr, 2, + [?sysDescr, TGenErr3]}) + end, + ?line ok = do_simple_get_next(7, + MgrNode, Addr, Port, Oids07, VF07), + + %% -- 8 -- + ?line {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig), + Oids08 = [TTooBig], + VF08 = fun(X) -> + verify_ssgn_reply2(X, {tooBig, 0, []}) + end, + ?line ok = do_simple_get_next(8, + MgrNode, Addr, Port, Oids08, VF08), + ok. + + +do_simple_get_next(N, Node, Addr, Port, Oids, Verify) -> + p("issue get-next command ~w", [N]), + case mgr_user_sync_get_next(Node, Addr, Port, Oids) of + {ok, Reply, Rem} -> + ?DBG("get-next ok:" + "~n Reply: ~p" + "~n Rem: ~w", [Reply, Rem]), + Verify(Reply); + + Error -> + {error, {unexpected_reply, Error}} + end. + + +verify_ssgn_reply1({noError, 0, _Vbs}, any) -> + ok; +verify_ssgn_reply1({noError, 0, Vbs}, Expected) -> + check_ssgn_vbs(Vbs, Expected); +verify_ssgn_reply1(R, _) -> + {error, {unexpected_reply, R}}. + +verify_ssgn_reply2({ErrStatus, ErrIdx, _Vbs}, {ErrStatus, ErrIdx, any}) -> + ok; +verify_ssgn_reply2({ErrStatus, ErrIdx, Vbs}, {ErrStatus, ErrIdx, Expected}) -> + check_ssgn_vbs(Vbs, Expected); +verify_ssgn_reply2(R, _) -> + {error, {unexpected_reply, R}}. + +check_ssgn_vbs([], []) -> + ok; +check_ssgn_vbs(Unexpected, []) -> + {error, {unexpected_vbs, Unexpected}}; +check_ssgn_vbs([], Expected) -> + {error, {expected_vbs, Expected}}; +check_ssgn_vbs([#varbind{value = endOfMibView}|R], + [endOfMibView|Expected]) -> + check_ssgn_vbs(R, Expected); +check_ssgn_vbs([#varbind{oid = Oid}|R], [Oid|Expected]) -> + check_ssgn_vbs(R, Expected); +check_ssgn_vbs([#varbind{oid = Oid, value = Value}|R], + [{Oid, Value}|Expected]) -> + check_ssgn_vbs(R, Expected); +check_ssgn_vbs([Vb|_], [E|_]) -> + {error, {unexpected_vb, Vb, E}}. + + +%%====================================================================== + +simple_sync_get_next2(doc) -> ["Simple (sync) get_next-request - " + "New style (TargetName)"]; +simple_sync_get_next2(suite) -> []; +simple_sync_get_next2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ssgn), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + TargetName = ?config(manager_agent_target_name, Config), + + %% -- 1 -- + Oids01 = [[1,3,7,1]], + VF01 = fun(X) -> verify_ssgn_reply1(X, [{[1,3,7,1],endOfMibView}]) end, + ?line ok = do_simple_get_next(1, + MgrNode, TargetName, Oids01, VF01), + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + + %% -- 2 -- + Oids02 = [[sysDescr], [1,3,7,1]], + VF02 = fun(X) -> + verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView]) + end, + ?line ok = do_simple_get_next(2, + MgrNode, TargetName, Oids02, VF02), + + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + %% -- 3 -- + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + Oids03 = [[TCnt2, 1]], + VF03 = fun(X) -> + verify_ssgn_reply1(X, [{fl([TCnt2,2]), 100}]) + end, + ?line ok = do_simple_get_next(3, + MgrNode, TargetName, Oids03, VF03), + + %% -- 4 -- + Oids04 = [[TCnt2, 2]], + VF04 = fun(X) -> + verify_ssgn_reply1(X, [{fl([TCnt2,2]), endOfMibView}]) + end, + ?line ok = do_simple_get_next(4, + MgrNode, TargetName, Oids04, VF04), + + %% -- 5 -- + ?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1), + Oids05 = [TGenErr1], + VF05 = fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]}) + end, + ?line ok = do_simple_get_next(5, + MgrNode, TargetName, Oids05, VF05), + + %% -- 6 -- + ?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2), + Oids06 = [TGenErr2], + VF06 = fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]}) + end, + ?line ok = do_simple_get_next(6, + MgrNode, TargetName, Oids06, VF06), + + %% -- 7 -- + ?line {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3), + Oids07 = [[sysDescr], TGenErr3], + VF07 = fun(X) -> + verify_ssgn_reply2(X, {genErr, 2, + [?sysDescr, TGenErr3]}) + end, + ?line ok = do_simple_get_next(7, + MgrNode, TargetName, Oids07, VF07), + + %% -- 8 -- + ?line {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig), + Oids08 = [TTooBig], + VF08 = fun(X) -> + verify_ssgn_reply2(X, {tooBig, 0, []}) + end, + ?line ok = do_simple_get_next(8, + MgrNode, TargetName, Oids08, VF08), + ok. + + +do_simple_get_next(N, Node, TargetName, Oids, Verify) -> + p("issue get-next command ~w", [N]), + case mgr_user_sync_get_next(Node, TargetName, Oids) of + {ok, Reply, Rem} -> + ?DBG("get-next ok:" + "~n Reply: ~p" + "~n Rem: ~w", [Reply, Rem]), + Verify(Reply); + + Error -> + {error, {unexpected_reply, Error}} + end. + + +%%====================================================================== + +simple_async_get_next1(doc) -> ["Simple (async) get_next-request - " + "Old style (Addr & Port)"]; +simple_async_get_next1(suite) -> []; +simple_async_get_next1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ssgn1), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + Addr = ?config(ip, Config), + Port = ?AGENT_PORT, + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + Exec = fun(X) -> + async_gn_exec1(MgrNode, Addr, Port, X) + end, + + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + ?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1), + ?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2), + ?line {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3), + ?line {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig), + + Requests = + [ + {1, + [[1,3,7,1]], + Exec, + fun(X) -> + verify_ssgn_reply1(X, [{[1,3,7,1], endOfMibView}]) + end}, + {2, + [[sysDescr], [1,3,7,1]], + Exec, + fun(X) -> + verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView]) + end}, + {3, + [[TCnt2, 1]], + Exec, + fun(X) -> + verify_ssgn_reply1(X, [{fl([TCnt2,2]), 100}]) + end}, + {4, + [[TCnt2, 2]], + Exec, + fun(X) -> + verify_ssgn_reply1(X, [{fl([TCnt2,2]), endOfMibView}]) + end}, + {5, + [TGenErr1], + Exec, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]}) + end}, + {6, + [TGenErr2], + Exec, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]}) + end}, + {7, + [[sysDescr], TGenErr3], + Exec, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 2, [TGenErr3]}) + end}, + {8, + [TTooBig], + Exec, + fun(X) -> + verify_ssgn_reply2(X, {tooBig, 0, []}) + end} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + + +async_gn_exec1(Node, Addr, Port, Oids) -> + mgr_user_async_get_next(Node, Addr, Port, Oids). + + +%%====================================================================== + +simple_async_get_next2(doc) -> ["Simple (async) get_next-request - " + "New style (TargetName)"]; +simple_async_get_next2(suite) -> []; +simple_async_get_next2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ssgn2), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + TargetName = ?config(manager_agent_target_name, Config), + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + Exec = fun(X) -> + async_gn_exec2(MgrNode, TargetName, X) + end, + + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + ?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1), + ?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2), + ?line {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3), + ?line {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig), + + Requests = + [ + {1, + [[1,3,7,1]], + Exec, + fun(X) -> + verify_ssgn_reply1(X, [{[1,3,7,1], endOfMibView}]) + end}, + {2, + [[sysDescr], [1,3,7,1]], + Exec, + fun(X) -> + verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView]) + end}, + {3, + [[TCnt2, 1]], + Exec, + fun(X) -> + verify_ssgn_reply1(X, [{fl([TCnt2,2]), 100}]) + end}, + {4, + [[TCnt2, 2]], + Exec, + fun(X) -> + verify_ssgn_reply1(X, [{fl([TCnt2,2]), endOfMibView}]) + end}, + {5, + [TGenErr1], + Exec, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]}) + end}, + {6, + [TGenErr2], + Exec, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]}) + end}, + {7, + [[sysDescr], TGenErr3], + Exec, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 2, [TGenErr3]}) + end}, + {8, + [TTooBig], + Exec, + fun(X) -> + verify_ssgn_reply2(X, {tooBig, 0, []}) + end} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + + +async_gn_exec2(Node, TargetName, Oids) -> + mgr_user_async_get_next(Node, TargetName, Oids). + + +%%====================================================================== + +simple_sync_set1(doc) -> ["Simple (sync) set-request - " + "Old style (Addr & Port)"]; +simple_sync_set1(suite) -> []; +simple_sync_set1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, sss1), + p("starting with Config: ~p~n", [Config]), + + Node = ?config(manager_node, Config), + Addr = ?config(ip, Config), + Port = ?AGENT_PORT, + + p("issue set-request without loading the mib"), + Val11 = "Arne Anka", + Val12 = "Stockholm", + VAVs1 = [ + {?sysName_instance, s, Val11}, + {?sysLocation_instance, s, Val12} + ], + ?line ok = do_simple_set1(Node, Addr, Port, VAVs1), + + p("issue set-request after first loading the mibs"), + ?line ok = mgr_user_load_mib(Node, std_mib()), + Val21 = "Sune Anka", + Val22 = "Gothenburg", + VAVs2 = [ + {[sysName, 0], Val21}, + {[sysLocation, 0], Val22} + ], + ?line ok = do_simple_set1(Node, Addr, Port, VAVs2), + ok. + +do_simple_set1(Node, Addr, Port, VAVs) -> + [SysName, SysLoc] = value_of_vavs(VAVs), + ?line {ok, Reply, Rem} = mgr_user_sync_set(Node, Addr, Port, VAVs), + + ?DBG("~n Reply: ~p" + "~n Rem: ~w", [Reply, Rem]), + + %% verify that the operation actually worked: + %% The order should be the same, so no need to seach + %% The value we get should be exactly the same as we sent + ?line ok = case Reply of + {noError, 0, [#varbind{oid = ?sysName_instance, + value = SysName}, + #varbind{oid = ?sysLocation_instance, + value = SysLoc}]} -> + ok; + {noError, 0, Vbs} -> + {error, {unexpected_vbs, Vbs}}; + Else -> + p("unexpected reply: ~n~p", [Else]), + {error, {unexpected_response, Else}} + end, + ok. + +value_of_vavs(VAVs) -> + value_of_vavs(VAVs, []). + +value_of_vavs([], Acc) -> + lists:reverse(Acc); +value_of_vavs([{_Oid, _Type, Val}|VAVs], Acc) -> + value_of_vavs(VAVs, [Val|Acc]); +value_of_vavs([{_Oid, Val}|VAVs], Acc) -> + value_of_vavs(VAVs, [Val|Acc]). + + +%%====================================================================== + +simple_sync_set2(doc) -> ["Simple (sync) set-request - New style (TargetName)"]; +simple_sync_set2(suite) -> []; +simple_sync_set2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, sss2), + p("starting with Config: ~p~n", [Config]), + + Node = ?config(manager_node, Config), + TargetName = ?config(manager_agent_target_name, Config), + + p("issue set-request without loading the mib"), + Val11 = "Arne Anka", + Val12 = "Stockholm", + VAVs1 = [ + {?sysName_instance, s, Val11}, + {?sysLocation_instance, s, Val12} + ], + ?line ok = do_simple_set2(Node, TargetName, VAVs1), + + p("issue set-request after first loading the mibs"), + ?line ok = mgr_user_load_mib(Node, std_mib()), + Val21 = "Sune Anka", + Val22 = "Gothenburg", + VAVs2 = [ + {[sysName, 0], Val21}, + {[sysLocation, 0], Val22} + ], + ?line ok = do_simple_set2(Node, TargetName, VAVs2), + ok. + +do_simple_set2(Node, TargetName, VAVs) -> + [SysName, SysLoc] = value_of_vavs(VAVs), + ?line {ok, Reply, Rem} = mgr_user_sync_set(Node, TargetName, VAVs), + + ?DBG("~n Reply: ~p" + "~n Rem: ~w", [Reply, Rem]), + + %% verify that the operation actually worked: + %% The order should be the same, so no need to seach + %% The value we get should be exactly the same as we sent + ?line ok = case Reply of + {noError, 0, [#varbind{oid = ?sysName_instance, + value = SysName}, + #varbind{oid = ?sysLocation_instance, + value = SysLoc}]} -> + ok; + {noError, 0, Vbs} -> + {error, {unexpected_vbs, Vbs}}; + Else -> + p("unexpected reply: ~n~p", [Else]), + {error, {unexpected_response, Else}} + end, + ok. + + +%%====================================================================== + +simple_async_set1(doc) -> ["Simple (async) set-request - " + "Old style (Addr & Port)"]; +simple_async_set1(suite) -> []; +simple_async_set1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, sas1), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + Addr = ?config(ip, Config), + Port = ?AGENT_PORT, + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + Exec = fun(X) -> + async_s_exec1(MgrNode, Addr, Port, X) + end, + + Requests = + [ + {1, + [{?sysName_instance, s, "Arne Anka"}], + Exec, + fun(X) -> + sas_verify(X, [?sysName_instance]) + end}, + {2, + [{?sysLocation_instance, s, "Stockholm"}, + {?sysName_instance, s, "Arne Anka"}], + Exec, + fun(X) -> + sas_verify(X, [?sysLocation_instance, ?sysName_instance]) + end}, + {3, + [{[sysName, 0], "Gothenburg"}, + {[sysLocation, 0], "Sune Anka"}], + Exec, + fun(X) -> + sas_verify(X, [?sysName_instance, ?sysLocation_instance]) + end} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + + +async_s_exec1(Node, Addr, Port, VAVs) -> + mgr_user_async_set(Node, Addr, Port, VAVs). + +sas_verify({noError, 0, _Vbs}, any) -> + p("verified [any]"), + ok; +sas_verify({noError, 0, Vbs}, Expected) -> + ?DBG("verified stage 1: " + "~n Vbs: ~p" + "~n Exp: ~p", [Vbs, Expected]), + sas_verify_vbs(Vbs, Expected); +sas_verify(Error, _) -> + {error, {unexpected_reply, Error}}. + +sas_verify_vbs([], []) -> + ok; +sas_verify_vbs(Vbs, []) -> + {error, {unexpected_vbs, Vbs}}; +sas_verify_vbs([], Exp) -> + {error, {expected_vbs, Exp}}; +sas_verify_vbs([#varbind{oid = Oid}|Vbs], [any|Exp]) -> + p("verified [any] oid ~w", [Oid]), + sas_verify_vbs(Vbs, Exp); +sas_verify_vbs([#varbind{oid = Oid, value = Value}|Vbs], [Oid|Exp]) -> + p("verified oid ~w [~p]", [Oid, Value]), + sas_verify_vbs(Vbs, Exp); +sas_verify_vbs([#varbind{oid = Oid, value = Value}|Vbs], [{Oid,Value}|Exp]) -> + p("verified oid ~w and ~p", [Oid, Value]), + sas_verify_vbs(Vbs, Exp); +sas_verify_vbs([Vb|_], [E|_]) -> + {error, {unexpected_vb, Vb, E}}. + + +%%====================================================================== + +simple_async_set2(doc) -> ["Simple (async) set-request - " + "New style (TargetName)"]; +simple_async_set2(suite) -> []; +simple_async_set2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, sas2), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + TargetName = ?config(manager_agent_target_name, Config), + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + Exec = fun(X) -> + async_s_exec2(MgrNode, TargetName, X) + end, + + Requests = + [ + {1, + [{?sysName_instance, s, "Arne Anka"}], + Exec, + fun(X) -> + sas_verify(X, [?sysName_instance]) + end}, + {2, + [{?sysLocation_instance, s, "Stockholm"}, + {?sysName_instance, s, "Arne Anka"}], + Exec, + fun(X) -> + sas_verify(X, [?sysLocation_instance, ?sysName_instance]) + end}, + {3, + [{[sysName, 0], "Gothenburg"}, + {[sysLocation, 0], "Sune Anka"}], + Exec, + fun(X) -> + sas_verify(X, [?sysName_instance, ?sysLocation_instance]) + end} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + + +async_s_exec2(Node, TargetName, VAVs) -> + mgr_user_async_set(Node, TargetName, VAVs). + + +%%====================================================================== + +simple_sync_get_bulk1(doc) -> ["Simple (sync) get_bulk-request - " + "Old style (Addr & Port)"]; +simple_sync_get_bulk1(suite) -> []; +simple_sync_get_bulk1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ssgb1), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + Addr = ?config(ip, Config), + Port = ?AGENT_PORT, + + %% -- 1 -- + ?line ok = do_simple_get_bulk1(1, + MgrNode, Addr, Port, 1, 1, [], + fun verify_ssgb_reply1/1), + + %% -- 2 -- + ?line ok = do_simple_get_bulk1(2, + MgrNode, Addr, Port, -1, 1, [], + fun verify_ssgb_reply1/1), + + %% -- 3 -- + ?line ok = do_simple_get_bulk1(3, + MgrNode, Addr, Port, -1, -1, [], + fun verify_ssgb_reply1/1), + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + %% -- 4 -- + VF04 = fun(X) -> + verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView]) + end, + ?line ok = do_simple_get_bulk1(4, + MgrNode, Addr, Port, + 2, 0, [[sysDescr],[1,3,7,1]], VF04), + + %% -- 5 -- + ?line ok = do_simple_get_bulk1(5, + MgrNode, Addr, Port, + 1, 2, [[sysDescr],[1,3,7,1]], VF04), + + %% -- 6 -- + VF06 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end, + ?line ok = do_simple_get_bulk1(6, + MgrNode, Addr, Port, + 0, 2, [[sysDescr],[1,3,7,1]], VF06), + + %% -- 7 -- + VF07 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end, + ?line ok = do_simple_get_bulk1(7, + MgrNode, Addr, Port, + 2, 2, + [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]], + VF07), + + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + %% -- 8 -- + VF08 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, + ?sysDescr_instance]) + end, + ?line ok = do_simple_get_bulk1(8, + MgrNode, Addr, Port, + 1, 2, + [[sysDescr],[sysDescr],[tTooBig]], + VF08), + + %% -- 9 -- + ?line ok = do_simple_get_bulk1(9, + MgrNode, Addr, Port, + 1, 12, + [[tDescr2], [sysDescr]], + fun verify_ssgb_reply1/1), + + %% -- 10 -- + VF10 = fun(X) -> + verify_ssgb_reply3(X, + [{?sysDescr, 'NULL'}, + {?sysObjectID, 'NULL'}, + {?tGenErr1, 'NULL'}, + {?sysDescr, 'NULL'}]) + end, + ?line ok = do_simple_get_bulk1(10, + MgrNode, Addr, Port, + 2, 2, + [[sysDescr], + [sysObjectID], + [tGenErr1], + [sysDescr]], + VF10), + + %% -- 11 -- + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + p("TCnt2: ~p", [TCnt2]), + VF11 = fun(X) -> + verify_ssgb_reply2(X, + [{fl([TCnt2,2]), 100}, + {fl([TCnt2,2]), endOfMibView}]) + end, + ?line ok = do_simple_get_bulk1(11, + MgrNode, Addr, Port, + 0, 2, + [[TCnt2, 1]], VF11), + + ok. + +fl(L) -> + lists:flatten(L). + +do_simple_get_bulk1(N, Node, Addr, Port, NonRep, MaxRep, Oids, Verify) -> + p("issue get-bulk command ~w", [N]), + case mgr_user_sync_get_bulk(Node, Addr, Port, NonRep, MaxRep, Oids) of + {ok, Reply, Rem} -> + ?DBG("get-bulk ok:" + "~n Reply: ~p" + "~n Rem: ~w", [Reply, Rem]), + Verify(Reply); + + Error -> + {error, {unexpected_reply, Error}} + end. + +verify_ssgb_reply1({noError, 0, []}) -> + ok; +verify_ssgb_reply1(X) -> + {error, {unexpected_reply, X}}. + +verify_ssgb_reply2({noError, 0, Vbs}, ExpectedVbs) -> + check_ssgb_vbs(Vbs, ExpectedVbs); +verify_ssgb_reply2(Error, _) -> + {error, {unexpected_reply, Error}}. + +verify_ssgb_reply3({genErr, 3, Vbs}, ExpectedVbs) -> + check_ssgb_vbs(Vbs, ExpectedVbs); +verify_ssgb_reply3(Unexpected, _) -> + {error, {unexpected_reply, Unexpected}}. + +check_ssgb_vbs([], []) -> + ok; +check_ssgb_vbs(Unexpected, []) -> + {error, {unexpected_vbs, Unexpected}}; +check_ssgb_vbs([], Expected) -> + {error, {expected_vbs, Expected}}; +check_ssgb_vbs([#varbind{value = endOfMibView}|R], + [endOfMibView|Expected]) -> + check_ssgb_vbs(R, Expected); +check_ssgb_vbs([#varbind{oid = Oid}|R], [Oid|Expected]) -> + check_ssgb_vbs(R, Expected); +check_ssgb_vbs([#varbind{oid = Oid, value = Value}|R], + [{Oid, Value}|Expected]) -> + check_ssgb_vbs(R, Expected); +check_ssgb_vbs([R|_], [E|_]) -> + {error, {unexpected_vb, R, E}}. + + +%%====================================================================== + +simple_sync_get_bulk2(doc) -> ["Simple (sync) get_bulk-request - " + "New style (TargetName)"]; +simple_sync_get_bulk2(suite) -> []; +simple_sync_get_bulk2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ssgb2), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + TargetName = ?config(manager_agent_target_name, Config), + + %% -- 1 -- + ?line ok = do_simple_get_bulk2(1, + MgrNode, TargetName, 1, 1, [], + fun verify_ssgb_reply1/1), + + %% -- 2 -- + ?line ok = do_simple_get_bulk2(2, + MgrNode, TargetName, -1, 1, [], + fun verify_ssgb_reply1/1), + + %% -- 3 -- + ?line ok = do_simple_get_bulk2(3, + MgrNode, TargetName, -1, -1, [], + fun verify_ssgb_reply1/1), + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + %% -- 4 -- + VF04 = fun(X) -> + verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView]) + end, + ?line ok = do_simple_get_bulk2(4, + MgrNode, TargetName, + 2, 0, [[sysDescr],[1,3,7,1]], VF04), + + %% -- 5 -- + ?line ok = do_simple_get_bulk2(5, + MgrNode, TargetName, + 1, 2, [[sysDescr],[1,3,7,1]], VF04), + + %% -- 6 -- + VF06 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end, + ?line ok = do_simple_get_bulk2(6, + MgrNode, TargetName, + 0, 2, [[sysDescr],[1,3,7,1]], VF06), + + %% -- 7 -- + VF07 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end, + ?line ok = do_simple_get_bulk2(7, + MgrNode, TargetName, + 2, 2, + [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]], + VF07), + + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + %% -- 8 -- + VF08 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, + ?sysDescr_instance]) + end, + ?line ok = do_simple_get_bulk2(8, + MgrNode, TargetName, + 1, 2, + [[sysDescr],[sysDescr],[tTooBig]], + VF08), + + %% -- 9 -- + ?line ok = do_simple_get_bulk2(9, + MgrNode, TargetName, + 1, 12, + [[tDescr2], [sysDescr]], + fun verify_ssgb_reply1/1), + + %% -- 10 -- + VF10 = fun(X) -> + verify_ssgb_reply3(X, + [{?sysDescr, 'NULL'}, + {?sysObjectID, 'NULL'}, + {?tGenErr1, 'NULL'}, + {?sysDescr, 'NULL'}]) + end, + ?line ok = do_simple_get_bulk2(10, + MgrNode, TargetName, + 2, 2, + [[sysDescr], + [sysObjectID], + [tGenErr1], + [sysDescr]], + VF10), + + %% -- 11 -- + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + p("TCnt2: ~p", [TCnt2]), + VF11 = fun(X) -> + verify_ssgb_reply2(X, + [{fl([TCnt2,2]), 100}, + {fl([TCnt2,2]), endOfMibView}]) + end, + ?line ok = do_simple_get_bulk2(11, + MgrNode, TargetName, + 0, 2, + [[TCnt2, 1]], VF11), + + ok. + +do_simple_get_bulk2(N, Node, TargetName, NonRep, MaxRep, Oids, Verify) -> + p("issue get-bulk command ~w", [N]), + case mgr_user_sync_get_bulk(Node, TargetName, NonRep, MaxRep, Oids) of + {ok, Reply, Rem} -> + ?DBG("get-bulk ok:" + "~n Reply: ~p" + "~n Rem: ~w", [Reply, Rem]), + Verify(Reply); + + Error -> + {error, {unexpected_reply, Error}} + end. + + +%%====================================================================== + +simple_async_get_bulk1(doc) -> ["Simple (async) get_bulk-request - " + "Old style (Addr & Port)"]; +simple_async_get_bulk1(suite) -> []; +simple_async_get_bulk1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, sagb1), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + Addr = ?config(ip, Config), + Port = ?AGENT_PORT, + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + Exec = fun(Data) -> + async_gb_exec1(MgrNode, Addr, Port, Data) + end, + + %% We re-use the verification functions from the ssgb test-case + VF04 = fun(X) -> + verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView]) + end, + VF06 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end, + VF07 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end, + VF08 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, + ?sysDescr_instance]) + end, + VF10 = fun(X) -> + verify_ssgb_reply3(X, + [{?sysDescr, 'NULL'}, + {?sysObjectID, 'NULL'}, + {?tGenErr1, 'NULL'}, + {?sysDescr, 'NULL'}]) + end, + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + VF11 = fun(X) -> + verify_ssgb_reply2(X, + [{fl([TCnt2,2]), 100}, + {fl([TCnt2,2]), endOfMibView}]) + end, + Requests = [ + { 1, + {1, 1, []}, + Exec, + fun verify_ssgb_reply1/1}, + { 2, + {-1, 1, []}, + Exec, + fun verify_ssgb_reply1/1}, + { 3, + {-1, -1, []}, + Exec, + fun verify_ssgb_reply1/1}, + { 4, + {2, 0, [[sysDescr],[1,3,7,1]]}, + Exec, + VF04}, + { 5, + {1, 2, [[sysDescr],[1,3,7,1]]}, + Exec, + VF04}, + { 6, + {0, 2, [[sysDescr],[1,3,7,1]]}, + Exec, + VF06}, + { 7, + {2, 2, [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]]}, + Exec, + VF07}, + { 8, + {1, 2, [[sysDescr],[sysDescr],[tTooBig]]}, + Exec, + VF08}, + { 9, + {1, 12, [[tDescr2], [sysDescr]]}, + Exec, + fun verify_ssgb_reply1/1}, + {10, + {2, 2, [[sysDescr],[sysObjectID], [tGenErr1],[sysDescr]]}, + Exec, + VF10}, + {11, + {0, 2, [[TCnt2, 1]]}, + Exec, + VF11}, + {12, + {2, 0, [[sysDescr],[1,3,7,1]]}, + Exec, + VF04}, + {13, + {1, 12, [[tDescr2], [sysDescr]]}, + Exec, + fun verify_ssgb_reply1/1}, + {14, + {2, 2, [[sysDescr],[sysObjectID],[tGenErr1],[sysDescr]]}, + Exec, + VF10}, + {15, + {0, 2, [[TCnt2, 1]]}, + Exec, + VF11}, + {16, + {2, 2, [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]]}, + Exec, + VF07}, + {17, + {2, 2, [[sysDescr],[sysObjectID], [tGenErr1],[sysDescr]]}, + Exec, + VF10} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + + +async_gb_exec1(Node, Addr, Port, {NR, MR, Oids}) -> + mgr_user_async_get_bulk(Node, Addr, Port, NR, MR, Oids). + + +%%====================================================================== + +simple_async_get_bulk2(doc) -> ["Simple (async) get_bulk-request - " + "New style (TargetName)"]; +simple_async_get_bulk2(suite) -> []; +simple_async_get_bulk2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, sagb2), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + TargetName = ?config(manager_agent_target_name, Config), + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + Exec = fun(Data) -> + async_gb_exec2(MgrNode, TargetName, Data) + end, + + %% We re-use the verification functions from the ssgb test-case + VF04 = fun(X) -> + verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView]) + end, + VF06 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end, + VF07 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end, + VF08 = fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, + ?sysDescr_instance]) + end, + VF10 = fun(X) -> + verify_ssgb_reply3(X, + [{?sysDescr, 'NULL'}, + {?sysObjectID, 'NULL'}, + {?tGenErr1, 'NULL'}, + {?sysDescr, 'NULL'}]) + end, + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + VF11 = fun(X) -> + verify_ssgb_reply2(X, + [{fl([TCnt2,2]), 100}, + {fl([TCnt2,2]), endOfMibView}]) + end, + Requests = [ + { 1, + {1, 1, []}, + Exec, + fun verify_ssgb_reply1/1}, + { 2, + {-1, 1, []}, + Exec, + fun verify_ssgb_reply1/1}, + { 3, + {-1, -1, []}, + Exec, + fun verify_ssgb_reply1/1}, + { 4, + {2, 0, [[sysDescr],[1,3,7,1]]}, + Exec, + VF04}, + { 5, + {1, 2, [[sysDescr],[1,3,7,1]]}, + Exec, + VF04}, + { 6, + {0, 2, [[sysDescr],[1,3,7,1]]}, + Exec, + VF06}, + { 7, + {2, 2, [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]]}, + Exec, + VF07}, + { 8, + {1, 2, [[sysDescr],[sysDescr],[tTooBig]]}, + Exec, + VF08}, + { 9, + {1, 12, [[tDescr2], [sysDescr]]}, + Exec, + fun verify_ssgb_reply1/1}, + {10, + {2, 2, [[sysDescr],[sysObjectID], [tGenErr1],[sysDescr]]}, + Exec, + VF10}, + {11, + {0, 2, [[TCnt2, 1]]}, + Exec, + VF11}, + {12, + {2, 0, [[sysDescr],[1,3,7,1]]}, + Exec, + VF04}, + {13, + {1, 12, [[tDescr2], [sysDescr]]}, + Exec, + fun verify_ssgb_reply1/1}, + {14, + {2, 2, [[sysDescr],[sysObjectID],[tGenErr1],[sysDescr]]}, + Exec, + VF10}, + {15, + {0, 2, [[TCnt2, 1]]}, + Exec, + VF11}, + {16, + {2, 2, [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]]}, + Exec, + VF07}, + {17, + {2, 2, [[sysDescr],[sysObjectID], [tGenErr1],[sysDescr]]}, + Exec, + VF10} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + + +async_gb_exec2(Node, TargetName, {NR, MR, Oids}) -> + mgr_user_async_get_bulk(Node, TargetName, NR, MR, Oids). + + +%%====================================================================== + +misc_async1(doc) -> ["Misc (async) request(s) - " + "Old style (Addr & Port)"]; +misc_async1(suite) -> []; +misc_async1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ms1), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + Addr = ?config(ip, Config), + Port = ?AGENT_PORT, + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + ExecG = fun(Data) -> + async_g_exec1(MgrNode, Addr, Port, Data) + end, + + ExecGN = fun(Data) -> + async_gn_exec1(MgrNode, Addr, Port, Data) + end, + + ExecS = fun(Data) -> + async_s_exec1(MgrNode, Addr, Port, Data) + end, + + ExecGB = fun(Data) -> + async_gb_exec1(MgrNode, Addr, Port, Data) + end, + + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + ?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1), + ?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2), + ?line {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3), + ?line {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig), + + Requests = + [ + { 1, + [?sysObjectID_instance], + ExecG, + fun(X) -> + sag_verify(X, [?sysObjectID_instance]) + end + }, + { 2, + {1, 1, []}, + ExecGB, + fun verify_ssgb_reply1/1}, + { 3, + {-1, 1, []}, + ExecGB, + fun verify_ssgb_reply1/1}, + { 4, + [{?sysLocation_instance, s, "Stockholm"}, + {?sysName_instance, s, "Arne Anka"}], + ExecS, + fun(X) -> + sas_verify(X, [?sysLocation_instance, ?sysName_instance]) + end}, + { 5, + [[sysDescr], [1,3,7,1]], + ExecGN, + fun(X) -> + verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView]) + end}, + { 6, + [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]], + ExecG, + fun(X) -> + sag_verify(X, [?sysObjectID_instance, + ?sysDescr_instance, + ?sysUpTime_instance]) + end}, + { 7, + [TGenErr2], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]}) + end}, + { 8, + {2, 0, [[sysDescr],[1,3,7,1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView]) + end}, + { 9, + {1, 2, [[sysDescr],[1,3,7,1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView]) + end}, + {10, + [TGenErr1], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]}) + end}, + {11, + {0, 2, [[sysDescr],[1,3,7,1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end}, + {12, + [{[sysName, 0], "Gothenburg"}, + {[sysLocation, 0], "Sune Anka"}], + ExecS, + fun(X) -> + sas_verify(X, [?sysName_instance, ?sysLocation_instance]) + end}, + {13, + {2, 2, [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end}, + {14, + {1, 2, [[sysDescr],[sysDescr],[tTooBig]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, + ?sysDescr_instance]) + end}, + {15, + {1, 12, [[tDescr2], [sysDescr]]}, + ExecGB, + fun verify_ssgb_reply1/1}, + {16, + {2, 2, [[sysDescr],[sysObjectID], [tGenErr1],[sysDescr]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply3(X, + [{?sysDescr, 'NULL'}, + {?sysObjectID, 'NULL'}, + {?tGenErr1, 'NULL'}, + {?sysDescr, 'NULL'}]) + end}, + {17, + [[sysDescr], TGenErr3], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 2, [TGenErr3]}) + end}, + {18, + {0, 2, [[TCnt2, 1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, + [{fl([TCnt2,2]), 100}, + {fl([TCnt2,2]), endOfMibView}]) + end}, + {19, + [TTooBig], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {tooBig, 0, []}) + end}, + {20, + [TTooBig], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {tooBig, 0, []}) + end} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + + +%%====================================================================== + +misc_async2(doc) -> ["Misc (async) request(s) - " + "New style (TargetName)"]; +misc_async2(suite) -> []; +misc_async2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, ms2), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + TargetName = ?config(manager_agent_target_name, Config), + + ?line ok = mgr_user_load_mib(MgrNode, std_mib()), + Test2Mib = test2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + + ExecG = fun(Data) -> + async_g_exec2(MgrNode, TargetName, Data) + end, + + ExecGN = fun(Data) -> + async_gn_exec2(MgrNode, TargetName, Data) + end, + + ExecS = fun(Data) -> + async_s_exec2(MgrNode, TargetName, Data) + end, + + ExecGB = fun(Data) -> + async_gb_exec2(MgrNode, TargetName, Data) + end, + + ?line {ok, [TCnt2|_]} = mgr_user_name_to_oid(MgrNode, tCnt2), + ?line {ok, [TGenErr1|_]} = mgr_user_name_to_oid(MgrNode, tGenErr1), + ?line {ok, [TGenErr2|_]} = mgr_user_name_to_oid(MgrNode, tGenErr2), + ?line {ok, [TGenErr3|_]} = mgr_user_name_to_oid(MgrNode, tGenErr3), + ?line {ok, [TTooBig|_]} = mgr_user_name_to_oid(MgrNode, tTooBig), + + Requests = + [ + { 1, + [?sysObjectID_instance], + ExecG, + fun(X) -> + sag_verify(X, [?sysObjectID_instance]) + end + }, + { 2, + {1, 1, []}, + ExecGB, + fun verify_ssgb_reply1/1}, + { 3, + {-1, 1, []}, + ExecGB, + fun verify_ssgb_reply1/1}, + { 4, + [{?sysLocation_instance, s, "Stockholm"}, + {?sysName_instance, s, "Arne Anka"}], + ExecS, + fun(X) -> + sas_verify(X, [?sysLocation_instance, ?sysName_instance]) + end}, + { 5, + [[sysDescr], [1,3,7,1]], + ExecGN, + fun(X) -> + verify_ssgn_reply1(X, [?sysDescr_instance, endOfMibView]) + end}, + { 6, + [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]], + ExecG, + fun(X) -> + sag_verify(X, [?sysObjectID_instance, + ?sysDescr_instance, + ?sysUpTime_instance]) + end}, + { 7, + [TGenErr2], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr2]}) + end}, + { 8, + {2, 0, [[sysDescr],[1,3,7,1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView]) + end}, + { 9, + {1, 2, [[sysDescr],[1,3,7,1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, [?sysDescr_instance, endOfMibView]) + end}, + {10, + [TGenErr1], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 1, [TGenErr1]}) + end}, + {11, + {0, 2, [[sysDescr],[1,3,7,1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end}, + {12, + [{[sysName, 0], "Gothenburg"}, + {[sysLocation, 0], "Sune Anka"}], + ExecS, + fun(X) -> + sas_verify(X, [?sysName_instance, ?sysLocation_instance]) + end}, + {13, + {2, 2, [[sysDescr],[1,3,7,1],[sysDescr],[1,3,7,1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, endOfMibView, + ?sysDescr_instance, endOfMibView, + ?sysObjectID_instance, endOfMibView]) + end}, + {14, + {1, 2, [[sysDescr],[sysDescr],[tTooBig]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, + [?sysDescr_instance, + ?sysDescr_instance]) + end}, + {15, + {1, 12, [[tDescr2], [sysDescr]]}, + ExecGB, + fun verify_ssgb_reply1/1}, + {16, + {2, 2, [[sysDescr],[sysObjectID], [tGenErr1],[sysDescr]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply3(X, + [{?sysDescr, 'NULL'}, + {?sysObjectID, 'NULL'}, + {?tGenErr1, 'NULL'}, + {?sysDescr, 'NULL'}]) + end}, + {17, + [[sysDescr], TGenErr3], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {genErr, 2, [TGenErr3]}) + end}, + {18, + {0, 2, [[TCnt2, 1]]}, + ExecGB, + fun(X) -> + verify_ssgb_reply2(X, + [{fl([TCnt2,2]), 100}, + {fl([TCnt2,2]), endOfMibView}]) + end}, + {19, + [TTooBig], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {tooBig, 0, []}) + end}, + {20, + [TTooBig], + ExecGN, + fun(X) -> + verify_ssgn_reply2(X, {tooBig, 0, []}) + end} + ], + + p("manager info when starting test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when starting test: ~n~p", [agent_info(AgentNode)]), + + ?line ok = async_exec(Requests, []), + + p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), + p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + + ok. + + +%%====================================================================== + +discovery(suite) -> []; +discovery(Config) when is_list(Config) -> + ?SKIP(not_yet_implemented). + + +%%====================================================================== +%% +%% Utility functions for cases trap1 and trap2 +%% + +collect_traps(N) -> + collect_traps(N, []). + +collect_traps(0, TrapInfo) -> + TrapInfo; +collect_traps(N, Acc) -> + receive + {async_event, _From, {trap, TrapInfo}} -> + p("collect_traps -> received trap: ~n ~p", [TrapInfo]), + collect_traps(N-1, [TrapInfo|Acc]) + after 10000 -> + p("collect_traps -> still awaiting ~w trap(s) - giving up", [N]), + Acc + end. + +verify_traps([], []) -> + p("verify_traps -> done"), + ok; +verify_traps([], Verifiers) -> + p("verify_traps -> done when ~w verifiers remain", [length(Verifiers)]), + {error, {failed_verify, [Id || {Id, _} <- Verifiers]}}; +verify_traps([Trap|Traps], Verifiers0) -> + p("verify_traps -> entry"), + case verify_trap(Trap, Verifiers0) of + {ok, Id} -> + p("verify_traps -> trap verified: ~p", [Id]), + Verifiers = lists:keydelete(Id, 1, Verifiers0), + verify_traps(Traps, Verifiers); + error -> + p("verify_traps -> failed verifying trap: ~n ~p", [Trap]), + {error, {failed_verifying_trap, Trap}} + end. + +verify_trap(Trap, []) -> + p("verify_trap -> could not verify trap:" + "~n Trap: ~p", [Trap]), + error; +verify_trap(Trap, [{Id, Verifier}|Verifiers]) -> + p("verify_trap -> entry with" + "~n Id: ~p" + "~n Trap: ~p", [Id, Trap]), + case Verifier(Trap) of + ok -> + p("verify_trap -> verified"), + {ok, Id}; + {error, _} -> + p("verify_trap -> not verified"), + verify_trap(Trap, Verifiers) + end. + + +%%====================================================================== + +trap1(suite) -> []; +trap1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,t1), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + + ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()), + Test2Mib = test2_mib(Config), + TestTrapMib = test_trap_mib(Config), + TestTrapv2Mib = test_trap_v2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, TestTrapMib), + ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib), + + %% Version 1 trap verification function: + VerifyTrap_v1 = + fun(Ent, Gen, Spec, ExpVBs, Trap) -> + case Trap of + {Ent, Gen, Spec, _Timestamp, VBs} -> + p("trap info as expected"), + case (catch validate_vbs(MgrNode, + ExpVBs, VBs)) of + ok -> + p("valid trap"), + ok; + Error -> + p("invalid trap: ~n Error: ~p", [Error]), + Error + end; + {Enteprise, Generic, Spec, Timestamp, VBs} -> + p("unepxected v1 trap info:" + "~n Enteprise: ~p" + "~n Generic: ~p" + "~n Spec: ~p" + "~n Timestamp: ~p" + "~n VBs: ~p", + [Enteprise, Generic, Spec, Timestamp, VBs]), + ExpTrap = {Ent, Gen, Spec, ignore, ExpVBs}, + Reason = {unexpected_trap, {ExpTrap, Trap}}, + {error, Reason}; + {Err, Idx, VBs} -> + p("unexpected trap info: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + end, + + %% Version 2 trap verification function: + VerifyTrap_v2 = + fun(ExpVBs, Trap) -> + case Trap of + {noError, 0, VBs0} -> + p("trap info as expected: ~n~p", [VBs0]), + %% The first two are a timestamp and oid + [_,_|VBs] = VBs0, + case (catch validate_vbs(MgrNode, + ExpVBs, VBs)) of + ok -> + p("valid trap"), + ok; + Error -> + p("invalid trap: ~n Error: ~p", + [Error]), + Error + end; + {Err, Idx, VBs} -> + p("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + end, + + + %% -- command 1 -- + %% Collect various info about the manager and the agent + Cmd1 = + fun() -> + p("manager info: ~n~p", [mgr_info(MgrNode)]), + p("agent info: ~n~p", [agent_info(AgentNode)]), + ok + end, + + %% -- command 2 -- + %% Make the agent send trap(s) (both a v1 and a v2 trap) + Cmd2 = + fun() -> + VBs = [{ifIndex, [1], 1}, + {ifAdminStatus, [1], 1}, + {ifOperStatus, [1], 2}], + agent_send_trap(AgentNode, linkUp, "standard trap", VBs), + ok + end, + + %% -- command 3 -- + %% Version 1 trap verify function + Cmd3_VerifyTrap_v1 = + fun(Trap) -> + Ent = [1,2,3], + Gen = 3, + Spec = 0, + ExpVBs = [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}], + VerifyTrap_v1(Ent, Gen, Spec, ExpVBs, Trap) + end, + + %% Version 2 trap verify function + Cmd3_VerifyTrap_v2 = + fun(Trap) -> + ExpVBs = [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}], + VerifyTrap_v2(ExpVBs, Trap) + end, + + %% Verify the two traps. The order of them is unknown + Cmd3 = + fun() -> + Verifiers = [{"v1 trap verifier", Cmd3_VerifyTrap_v1}, + {"v2 trap verifier", Cmd3_VerifyTrap_v2}], + verify_traps(collect_traps(2), Verifiers) + end, + + Cmd4 = fun() -> ?SLEEP(1000), ok end, + + Commands = + [ + {1, "Manager and agent info at start of test", Cmd1}, + {2, "Send trap from agent", Cmd2}, + {3, "Await trap(s) to manager", Cmd3}, + {4, "Sleep some time (1 sec)", Cmd4}, + {5, "Manager and agent info after test completion", Cmd1} + ], + + command_handler(Commands). + + +%%====================================================================== + +trap2(suite) -> []; +trap2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,t2), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + + ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()), + Test2Mib = test2_mib(Config), + TestTrapMib = test_trap_mib(Config), + TestTrapv2Mib = test_trap_v2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, TestTrapMib), + ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib), + + %% Version 1 trap verification function: + VerifyTrap_v1 = + fun(Ent, Gen, Spec, ExpVBs, Trap) -> + case Trap of + {Ent, Gen, Spec, _Timestamp, VBs} -> + p("trap info as expected"), + case (catch validate_vbs(MgrNode, + ExpVBs, VBs)) of + ok -> + p("valid trap"), + ok; + Error -> + p("invalid trap: ~n Error: ~p", [Error]), + Error + end; + {Enteprise, Generic, Spec, Timestamp, VBs} -> + p("unepxected v1 trap info:" + "~n Enteprise: ~p" + "~n Generic: ~p" + "~n Spec: ~p" + "~n Timestamp: ~p" + "~n VBs: ~p", + [Enteprise, Generic, Spec, Timestamp, VBs]), + ExpTrap = {Ent, Gen, Spec, ignore, ExpVBs}, + Reason = {unexpected_trap, {ExpTrap, Trap}}, + {error, Reason}; + {Err, Idx, VBs} -> + p("unexpected trap info: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + end, + + %% Version 2 trap verification function: + VerifyTrap_v2 = + fun(ExpVBs, Trap) -> + case Trap of + {noError, 0, VBs0} -> + p("trap info as expected: ~n~p", [VBs0]), + %% The first two are a timestamp and oid + [_,_|VBs] = VBs0, + case (catch validate_vbs(MgrNode, + ExpVBs, VBs)) of + ok -> + p("valid trap"), + ok; + Error -> + p("invalid trap: ~n Error: ~p", + [Error]), + Error + end; + {Err, Idx, VBs} -> + p("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + end, + + %% -- command 1 -- + %% Collect various info about the manager and the agent + Cmd1 = + fun() -> + p("manager info: ~n~p", [mgr_info(MgrNode)]), + p("agent info: ~n~p", [agent_info(AgentNode)]), + ok + end, + + %% -- command 2 -- + %% Make the agent send trap(s) (both a v1 and a v2 trap) + Cmd2 = + fun() -> + VBs = [{sysContact, "pelle"}], + agent_send_trap(AgentNode, testTrap1, "standard trap", VBs), + ok + end, + + %% -- command 3 -- + %% Version 1 trap verify function + Cmd3_VerifyTrap_v1 = + fun(Trap) -> + Ent = [1,2,3], + Gen = 1, + Spec = 0, + ExpVBs = [{[system, [4,0]], "pelle"}], + VerifyTrap_v1(Ent, Gen, Spec, ExpVBs, Trap) + end, + + %% Version 2 trap verify function + Cmd3_VerifyTrap_v2 = + fun(Trap) -> + ExpVBs = [{[system, [4,0]], "pelle"}, + {[snmpTrapEnterprise,0], any}], + VerifyTrap_v2(ExpVBs, Trap) + end, + + %% Verify the two traps. The order of them is unknown + Cmd3 = + fun() -> + Verifiers = [{"v1 trap verifier", Cmd3_VerifyTrap_v1}, + {"v2 trap verifier", Cmd3_VerifyTrap_v2}], + verify_traps(collect_traps(2), Verifiers) + end, + + %% -- command 4 -- + %% Make the agent send another set of trap(s) (both a v1 and a v2 trap) + Cmd4 = + fun() -> + VBs = [{ifIndex, [1], 1}, + {ifAdminStatus, [1], 1}, + {ifOperStatus, [1], 2}], + agent_send_trap(AgentNode, linkUp, "standard trap", VBs), + ok + end, + + + %% -- command 5 -- + %% Expected varbinds + ExpVBs5 = [{[ifIndex, 1], 1}, + {[ifAdminStatus, 1], 1}, + {[ifOperStatus, 1], 2}], + + + %% Version 1 trap verify function + Cmd5_VerifyTrap_v1 = + fun(Trap) -> + Ent = [1,2,3], + Gen = 3, + Spec = 0, + VerifyTrap_v1(Ent, Gen, Spec, ExpVBs5, Trap) + end, + + %% Version 2 trap verify function + Cmd5_VerifyTrap_v2 = + fun(Trap) -> + VerifyTrap_v2(ExpVBs5, Trap) + end, + + %% Verify the two traps. The order of them is unknown + Cmd5 = + fun() -> + Verifiers = [{"v1 trap verifier", Cmd5_VerifyTrap_v1}, + {"v2 trap verifier", Cmd5_VerifyTrap_v2}], + verify_traps(collect_traps(2), Verifiers) + end, + + %% -- command 6 -- + %% Some sleep before we are done + Cmd6 = fun() -> ?SLEEP(1000), ok end, + + Commands = + [ + {1, "Manager and agent info at start of test", Cmd1}, + {2, "Send first trap(s) from agent", Cmd2}, + {3, "Await the trap(s) from agent", Cmd3}, + {4, "Send second trap(s) from agent", Cmd4}, + {5, "Await the trap(s) from the agent", Cmd5}, + {6, "Sleep some time (1 sec)", Cmd6}, + {7, "Manager and agent info after test completion", Cmd1} + ], + + command_handler(Commands). + + +%%====================================================================== + +inform1(suite) -> []; +inform1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,i1), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + + ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()), + Test2Mib = test2_mib(Config), + TestTrapMib = test_trap_mib(Config), + TestTrapv2Mib = test_trap_v2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, TestTrapMib), + ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib), + + + Cmd1 = + fun() -> + p("manager info: ~n~p", [mgr_info(MgrNode)]), + p("manager system info: ~n~p", [mgr_sys_info(MgrNode)]), + p("agent info: ~n~p", [agent_info(AgentNode)]), + ok + end, + + Cmd2 = + fun() -> + agent_send_notif(AgentNode, testTrapv22, "standard inform"), + ok + end, + + Cmd3 = + fun() -> + receive + {async_event, From, {inform, Pid, Inform}} -> + p("received inform"), + case Inform of + {noError, 0, VBs} when is_list(VBs) -> + case (catch validate_testTrapv22_vbs(MgrNode, + VBs)) of + ok -> + p("valid inform"), + Pid ! {handle_inform_no_response, + From}, + ok; + Error -> + p("invalid inform: ~n Error: ~p", + [Error]), + Error + end; + {Err, Idx, VBs} -> + p("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + after 10000 -> + receive + Any -> + {error, {timeout_crap, Any}} + after 1000 -> + {error, timeout} + end + end + end, + + Cmd4 = + fun() -> + receive + {async_event, From, {inform, Pid, Inform}} -> + p("received inform"), + case Inform of + {noError, 0, VBs} when is_list(VBs) -> + case (catch validate_testTrapv22_vbs(MgrNode, + VBs)) of + ok -> + p("valid inform"), + Pid ! {handle_inform_response, From}, + ok; + Error -> + p("invalid inform: ~n Error: ~p", + [Error]), + Error + end; + {Err, Idx, VBs} -> + p("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + after 20000 -> + receive + Any -> + {error, {timeout_crap, Any}} + after 1000 -> + {error, timeout} + end + end + end, + + Cmd5 = fun() -> ?SLEEP(5000), ok end, + + Commands = + [ + {1, "Manager and agent info at start of test", Cmd1}, + {2, "Send notifcation [no receiver] from agent", Cmd2}, + {3, "Await first inform to manager - do not reply", Cmd3}, + {4, "Await second inform to manager - reply", Cmd4}, + {5, "Sleep some time (5 sec)", Cmd5}, + {6, "Manager and agent info after test completion", Cmd1} + ], + + command_handler(Commands). + + +%%====================================================================== + +inform2(suite) -> []; +inform2(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,i2), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + %% Addr = ?config(ip, Config), + %% Port = ?AGENT_PORT, + + ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()), + Test2Mib = test2_mib(Config), + TestTrapMib = test_trap_mib(Config), + TestTrapv2Mib = test_trap_v2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, TestTrapMib), + ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib), + + Cmd1 = + fun() -> + p("manager info: ~n~p", [mgr_info(MgrNode)]), + p("agent info: ~n~p", [agent_info(AgentNode)]), + ok + end, + + Cmd2 = + fun() -> + agent_send_notif(AgentNode, + testTrapv22, + {inform2_tag1, self()}, + "standard inform", + []), + ok + end, + + Cmd3 = + fun() -> + receive + {snmp_targets, inform2_tag1, Addrs} -> + p("sent inform to ~p", [Addrs]), + ok + after 10000 -> + receive + Any -> + {error, {timeout_crap, Any}} + after 1000 -> + {error, timeout} + end + end + end, + + Cmd4 = + fun() -> + receive + {async_event, From, {inform, Pid, Inform}} -> + p("received inform"), + case Inform of + {noError, 0, VBs} when is_list(VBs) -> + case (catch validate_testTrapv22_vbs(MgrNode, + VBs)) of + ok -> + p("valid inform"), + Pid ! {handle_inform_no_response, + From}, + ok; + Error -> + p("invalid inform: ~n Error: ~p", + [Error]), + Error + end; + {Err, Idx, VBs} -> + p("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + after 10000 -> + receive + Any -> + {error, {timeout_crap, Any}} + after 1000 -> + {error, timeout} + end + end + end, + + Cmd5 = + fun() -> + receive + {async_event, From, {inform, Pid, Inform}} -> + p("received inform"), + case Inform of + {noError, 0, VBs} when is_list(VBs) -> + case (catch validate_testTrapv22_vbs(MgrNode, + VBs)) of + ok -> + p("valid inform"), + Pid ! {handle_inform_response, From}, + ok; + Error -> + p("invalid inform: ~n Error: ~p", + [Error]), + Error + end; + {Err, Idx, VBs} -> + p("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + after 20000 -> + receive + Any -> + {error, {timeout_crap, Any}} + after 1000 -> + {error, timeout} + end + end + end, + + Cmd6 = + fun() -> + receive + {snmp_notification, inform2_tag1, {got_response, Addr}} -> + p("received expected \"got response\" notification " + "from: " + "~n ~p", [Addr]), + ok; + {snmp_notification, inform2_tag1, {no_response, Addr}} -> + p("<ERROR> received expected \"no response\" " + "notification from: " + "~n ~p", [Addr]), + {error, no_response} + after 10000 -> + receive + Any -> + {error, {timeout_crap, Any}} + after 1000 -> + {error, timeout} + end + end + end, + + Cmd7 = fun() -> ?SLEEP(5000), ok end, + + Commands = + [ + {1, "Manager and agent info at start of test", Cmd1}, + {2, "Send notifcation [no receiver] from agent", Cmd2}, + {3, "await inform-sent acknowledge from agent", Cmd3}, + {4, "Await first inform to manager - do not reply", Cmd4}, + {5, "Await second inform to manager - reply", Cmd5}, + {6, "await inform-acknowledge from agent", Cmd6}, + {7, "Sleep some time (5 sec)", Cmd7}, + {8, "Manager and agent info after test completion", Cmd1} + ], + + command_handler(Commands). + + +%%====================================================================== + +inform3(suite) -> []; +inform3(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,i3), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + + ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()), + Test2Mib = test2_mib(Config), + TestTrapMib = test_trap_mib(Config), + TestTrapv2Mib = test_trap_v2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, TestTrapMib), + ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib), + + Cmd1 = + fun() -> + p("manager info: ~n~p", [mgr_info(MgrNode)]), + p("agent info: ~n~p", [agent_info(AgentNode)]), + ok + end, + + Cmd2 = + fun() -> + agent_send_notif(AgentNode, + testTrapv22, + {inform3_tag1, self()}, + "standard inform", + []), + ok + end, + + Cmd3 = + fun() -> + receive + {snmp_targets, inform3_tag1, [_Addr]} -> + p("received inform-sent acknowledgement", []), + ok + after 10000 -> + receive + Crap -> + {error, {timeout_crap, Crap}} + after 0 -> + {error, timeout} + end + end + end, + + Cmd4 = + fun() -> + receive + {async_event, From, {inform, Pid, Inform}} -> + p("received inform"), + case Inform of + {noError, 0, VBs} when is_list(VBs) -> + case (catch validate_testTrapv22_vbs(MgrNode, + VBs)) of + ok -> + p("valid inform"), + Pid ! {handle_inform_no_response, + From}, + ok; + Error -> + p("invalid inform: ~n Error: ~p", + [Error]), + Error + end; + {Err, Idx, VBs} -> + p("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + after 50000 -> + receive + Any -> + {error, {timeout_crap, Any}} + after 0 -> + {error, timeout} + end + end + end, + + Cmd7 = + fun() -> + receive + {snmp_notification, inform3_tag1, {no_response, Addr}} -> + p("received expected \"no response\" notification " + "from: " + "~n ~p", [Addr]), + ok; + {snmp_notification, inform3_tag1, {got_response, Addr}} -> + p("<ERROR> received unexpected \"got response\" " + "notification from: " + "~n ~p", + [Addr]), + {error, {got_response, Addr}} + after 120000 -> + receive + Crap -> + {error, {timeout_crap, Crap}} + after 0 -> + {error, timeout} + end + end + end, + + Cmd8 = fun() -> ?SLEEP(1000), ok end, + + Commands = + [ + {1, "Manager and agent info at start of test", Cmd1}, + {2, "Send notifcation from agent", Cmd2}, + {3, "await inform-sent acknowledge from agent", Cmd3}, + {4, "Await first inform to manager - do not reply", Cmd4}, + {5, "Await first inform to manager - do not reply", Cmd4}, + {6, "Await first inform to manager - do not reply", Cmd4}, + {7, "await inform-acknowledge from agent", Cmd7}, + {8, "Sleep some time (1 sec)", Cmd8}, + {9, "Manager and agent info after test completion", Cmd1} + ], + + command_handler(Commands). + + +%%====================================================================== + +inform4(suite) -> []; +inform4(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname,i4), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + + ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()), + Test2Mib = test2_mib(Config), + TestTrapMib = test_trap_mib(Config), + TestTrapv2Mib = test_trap_v2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, TestTrapMib), + ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib), + + Cmd1 = + fun() -> + p("manager info: ~n~p", [mgr_info(MgrNode)]), + p("agent info: ~n~p", [agent_info(AgentNode)]), + ok + end, + + Cmd2 = + fun() -> + agent_send_notif(AgentNode, testTrapv22, "standard inform"), + ok + end, + + Cmd3 = + fun() -> + receive + {async_event, From, {inform, Pid, Inform}} -> + p("received inform"), + case Inform of + {noError, 0, VBs} when is_list(VBs) -> + case (catch validate_testTrapv22_vbs(MgrNode, + VBs)) of + ok -> + p("valid inform"), + %% Actually, as we have + %% configured the manager in + %% this test case (irb = auto) + %% it has already responded + Pid ! {handle_inform_response, From}, + ok; + Error -> + p("invalid inform: ~n Error: ~p", + [Error]), + Error + end; + {Err, Idx, VBs} -> + p("unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end + after 20000 -> + receive + Any -> + {error, {crap, Any}} + after 1000 -> + {error, timeout} + end + end + end, + + %% This is the a result of erroneous configuration. +%% Cmd4 = +%% fun() -> +%% receive +%% {async_event, _ReqId, {error, Reason}} -> +%% p("received error"), +%% case Reason of +%% {failed_processing_message, +%% {securityError, usmStatsUnknownEngineIDs}} -> +%% p("expected error"), +%% ok; +%% _ -> +%% p("unexpected error: " +%% "~n Reason: ~p", [Reason]), +%% {error, {unexpected_error, Reason}} +%% end +%% after 20000 -> +%% receive +%% Any -> +%% {error, {crap, Any}} +%% after 1000 -> +%% {error, timeout} +%% end +%% end +%% end, + + Cmd5 = fun() -> ?SLEEP(1000), ok end, + + Commands = + [ + {1, "Manager and agent info at start of test", Cmd1}, + {2, "Send notifcation [no receiver] from agent", Cmd2}, + {3, "Await inform to manager", Cmd3}, +%% {4, "Await error info (because of erroneous config)", Cmd4}, + {5, "Sleep some time (1 sec)", Cmd5}, + {6, "Manager and agent info after test completion", Cmd1} + ], + + command_handler(Commands). + + +%%====================================================================== +%% +%% Test: ts:run(snmp, snmp_manager_test, inform_swarm, [batch]). + +inform_swarm(suite) -> []; +inform_swarm(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, is), + p("starting with Config: ~p~n", [Config]), + + MgrNode = ?config(manager_node, Config), + AgentNode = ?config(agent_node, Config), + + ?line ok = mgr_user_load_mib(MgrNode, snmpv2_mib()), + Test2Mib = test2_mib(Config), + TestTrapMib = test_trap_mib(Config), + TestTrapv2Mib = test_trap_v2_mib(Config), + ?line ok = mgr_user_load_mib(MgrNode, Test2Mib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapMib), + ?line ok = mgr_user_load_mib(MgrNode, TestTrapv2Mib), + ?line ok = agent_load_mib(AgentNode, Test2Mib), + ?line ok = agent_load_mib(AgentNode, TestTrapMib), + ?line ok = agent_load_mib(AgentNode, TestTrapv2Mib), + NumInforms = 100, + + Collector = self(), + + Generator = + erlang:spawn( + fun() -> + receive + {Collector, start} -> + ok + end, + Seqs = lists:seq(1, NumInforms), + lists:foreach( + fun(N) -> + p("send notification ~w", [N]), + agent_send_notif(AgentNode, + testTrapv22, + {{inform2_tag1, N}, Collector}, + "standard inform", + []), + %% Sleep some [(N div 10)*100 ms] + %% every tenth notification + if + N rem 10 == 0 -> + %% Time to sleep some + Sleep = (N div 10) * 50, + p("sleep ~w [~w]", [Sleep, N]), + ?SLEEP(Sleep); + true -> + ok + end + end, + Seqs), + ok + end), + + Cmd1 = + fun() -> + p("manager info: ~n~p", [mgr_info(MgrNode)]), + p("agent info: ~n~p", [agent_info(AgentNode)]), + ok + end, + + Cmd2 = fun() -> Generator ! {Collector, start}, ok end, + + Cmd3 = + fun() -> + inform_swarm_collector(NumInforms) + end, + + + Cmd4 = fun() -> ?SLEEP(1000), ok end, + + Commands = + [ + {1, "Manager and agent info at start of test", Cmd1}, + {2, "Send notifcation(s) from agent", Cmd2}, + {3, "Await send-ack(s)/inform(s)/response(s)", Cmd3}, + {4, "Sleep some time (1 sec)", Cmd4}, + {5, "Manager and agent info after test completion", Cmd1} + ], + + command_handler(Commands). + +inform_swarm_collector(N) -> + inform_swarm_collector(N, 0, 0, 0, 10000). + +%% Note that we need to deal with re-transmissions! +%% That is, the agent did not receive the ack in time, +%% and therefor did a re-transmit. This means that we +%% expect to receive more inform's then we actually +%% sent. So for sucess we assume: +%% +%% SentAckCnt = N +%% RespCnt = N +%% RecvCnt >= N +%% +inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, _) + when ((N == SentAckCnt) and + (N == RespCnt) and + (N >= RecvCnt)) -> + p("inform_swarm_collector -> done when" + "~n N: ~w" + "~n SentAckCnt: ~w" + "~n RecvCnt: ~w" + "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]), + ok; +inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt, Timeout) -> + p("inform_swarm_collector -> entry with" + "~n N: ~w" + "~n SentAckCnt: ~w" + "~n RecvCnt: ~w" + "~n RespCnt: ~w", [N, SentAckCnt, RecvCnt, RespCnt]), + receive + {snmp_targets, {inform2_tag1, Id}, [_Addr]} -> + p("received inform-sent acknowledgement for ~w", [Id]), + inform_swarm_collector(N, SentAckCnt+1, RecvCnt, RespCnt, + Timeout); + + %% The manager has received the actual inform + {async_event, From, {inform, Pid, Inform}} -> + p("received inform"), + case Inform of + {noError, 0, VBs} when is_list(VBs) -> + Pid ! {handle_inform_response, From}, + inform_swarm_collector(N, SentAckCnt, RecvCnt+1, RespCnt, + Timeout); + {Err, Idx, VBs} -> + p("<ERROR> unexpected error status: " + "~n Err: ~p" + "~n Idx: ~p" + "~n VBs: ~p", [Err, Idx, VBs]), + Reason = {unexpected_status, {Err, Idx, VBs}}, + {error, Reason} + end; + + %% The agent has received ack from the manager + {snmp_notification, {inform2_tag1, Id}, {got_response, Addr}} -> + p("received expected \"got response\" for ~w" + "notification from: " + "~n ~p", + [Id, Addr]), + inform_swarm_collector(N, SentAckCnt, RecvCnt, RespCnt+1, + Timeout); + + %% The agent did not received ack from the manager in time + {snmp_notification, inform2_tag1, {no_response, Addr}} -> + p("<ERROR> received expected \"no response\" notification " + "from: " + "~n ~p", [Addr]), + Reason = {no_response, Addr, {N, SentAckCnt, RecvCnt, RespCnt}}, + {error, Reason} + + after Timeout -> + %% Give up when we have been dead in the water for Timeout ms + {error, {timeout, N, SentAckCnt, RecvCnt, RespCnt}} + end. + + +%%====================================================================== + +report(suite) -> []; +report(Config) when is_list(Config) -> + ?SKIP(not_yet_implemented). + + + +%%====================================================================== + +otp8015_1(doc) -> ["OTP-8015:1 - testing the new api-function."]; +otp8015_1(suite) -> []; +otp8015_1(Config) when is_list(Config) -> + process_flag(trap_exit, true), + put(tname, otp8015_1), + p("starting with Config: ~p~n", [Config]), + + ConfDir = ?config(manager_conf_dir, Config), + DbDir = ?config(manager_db_dir, Config), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + snmpm:load_mib(std_mib()), + snmpm:load_mib(test_trap_mib(Config)), + + p("manager started, now sleep some"), + + ?SLEEP(1000), + + p("loaded mibs: ~p", [snmpm:which_mibs()]), + + p("get some type(s) from the mibs"), + {ok, 'Counter32'} = snmpm:oid_to_type(?snmpOutTraps), + {ok, [IfIndex]} = snmpm:name_to_oid(ifIndex), + {ok, 'INTEGER'} = snmpm:oid_to_type(IfIndex), + + + p("stop manager"), + ok = snmpm:stop(), + + ?SLEEP(1000), + + p("end"), + ok. + + +%%====================================================================== +%% async snmp utility functions +%%====================================================================== + +async_exec([], Acc) -> + p("all async request's sent => now await reponses"), + async_verify(async_collector(Acc, [])); +async_exec([{Id, Data, Exec, Ver}|Reqs], Acc) -> + p("issue async request ~w", [Id]), + ?line {ok, ReqId} = Exec(Data), + async_exec(Reqs, [{ReqId, Id, Ver}|Acc]). + +async_collector([], Acc) -> + p("received replies for all requests - now sort"), + lists:keysort(1, Acc); +async_collector(Expected, Acc) -> + receive + {async_event, ReqId, Reply} -> + p("received async event with request-id ~w", [ReqId]), + case lists:keysearch(ReqId, 1, Expected) of + {value, {_, Id, Ver}} -> + p("event was for request ~w", [Id]), + Expected2 = lists:keydelete(ReqId, 1, Expected), + async_collector(Expected2, [{Id, Ver, Reply}|Acc]); + false -> + % Duplicate reply? + ?FAIL({unexpected_async_event, ReqId, Reply}) + end + after 10000 -> + ?FAIL({timeout, {Expected, Acc}}) + end. + +async_verify([]) -> + ok; +async_verify([{Id, Verify, Reply}|Replies]) -> + p("verify reply ~w", [Id]), + Verify(Reply), + async_verify(Replies). + + + +%%====================================================================== +%% Internal functions +%%====================================================================== + + +%% -- Verify varbinds -- + +validate_vbs(Node, ExpVBs, VBs) -> + validate_vbs(purify_oids(Node, ExpVBs), VBs). + +validate_testTrapv22_vbs(Node, VBs) -> + ExpVBs = [{[sysUpTime, 0], any}, + {[snmpTrapOID, 0], ?system ++ [0,1]}], + validate_vbs(purify_oids(Node, ExpVBs), VBs). + +validate_vbs([], []) -> + ok; +validate_vbs(Exp, []) -> + {error, {expected_vbs, Exp}}; +validate_vbs([], VBs) -> + {error, {unexpected_vbs, VBs}}; +validate_vbs([any|Exp], [_|VBs]) -> + validate_vbs(Exp, VBs); +validate_vbs([{_, any}|Exp], [#varbind{}|VBs]) -> + validate_vbs(Exp, VBs); +validate_vbs([{Oid, Val}|Exp], [#varbind{oid = Oid, value = Val}|VBs]) -> + validate_vbs(Exp, VBs); +validate_vbs([{Oid, Val1}|_], [#varbind{oid = Oid, value = Val2}|_]) -> + {error, {unexpected_vb_value, Oid, Val1, Val2}}; +validate_vbs([{Oid1, _}|_], [#varbind{oid = Oid2}|_]) -> + {error, {unexpected_vb_oid, Oid1, Oid2}}. + +purify_oids(_, []) -> + []; +purify_oids(Node, [{Oid, Val}|Oids]) -> + [{purify_oid(Node, Oid), Val}| purify_oids(Node, Oids)]. + +purify_oid(Node, Oid) -> + case mgr_user_purify_oid(Node, Oid) of + Oid2 when is_list(Oid2) -> + Oid2; + {error, _} = Error -> + throw(Error) + end. + + +%% -- Test case command handler (executor) --- + +command_handler([]) -> + ok; +command_handler([{No, Desc, Cmd}|Cmds]) -> + p("command_handler -> command ~w: " + "~n ~s", [No, Desc]), + case (catch Cmd()) of + ok -> + p("command_handler -> ~w: ok",[No]), + command_handler(Cmds); + {error, Reason} -> + p("<ERROR> command_handler -> ~w error: ~n~p",[No, Reason]), + ?line ?FAIL({command_failed, No, Reason}); + Error -> + p("<ERROR> command_handler -> ~w unexpected: ~n~p",[No, Error]), + ?line ?FAIL({unexpected_command_result, No, Error}) + end. + + +%% -- Misc manager functions -- + +init_manager(AutoInform, Config) -> + ?LOG("init_manager -> entry with" + "~n AutoInform: ~p" + "~n Config: ~p", [AutoInform, Config]), + + + %% -- + %% Start node + %% + + ?line Node = start_manager_node(), + + + %% -- + %% Start and initiate crypto on manager node + %% + + ?line ok = init_crypto(Node), + + %% + %% Write manager config + %% + + ?line ok = write_manager_config(Config), + + IRB = case AutoInform of + true -> + auto; + _ -> + user + end, + Conf = [{manager_node, Node}, {irb, IRB} | Config], + Vsns = [v1,v2,v3], + start_manager(Node, Vsns, Conf). + +fin_manager(Config) -> + Node = ?config(manager_node, Config), + stop_manager(Node, Config), + fin_crypto(Node), + stop_node(Node), + Config. + + +%% -- Misc agent functions -- + +init_agent(Config) -> + ?LOG("init_agent -> entry with" + "~n Config: ~p", [Config]), + + %% -- + %% Retrieve some dir's + %% + Dir = ?config(top_dir, Config), + DataDir = ?config(data_dir, Config), + + %% -- + %% Start node + %% + + ?line Node = start_agent_node(), + + + %% -- + %% Start and initiate mnesia on agent node + %% + + ?line ok = init_mnesia(Node, Dir), + + + %% -- + %% Start and initiate crypto on agent node + %% + + ?line ok = init_crypto(Node), + + + %% + %% Write agent config + %% + + Vsns = [v1,v2], + ?line ok = write_agent_config(Vsns, Config), + + Conf = [{agent_node, Node}, + {mib_dir, DataDir} | Config], + + %% + %% Start the agent + %% + + start_agent(Node, Vsns, Conf). + +fin_agent(Config) -> + Node = ?config(agent_node, Config), + stop_agent(Node, Config), + fin_crypto(Node), + fin_mnesia(Node), + stop_node(Node), + Config. + +init_mnesia(Node, Dir) -> + ?DBG("init_mnesia -> load application mnesia", []), + ?line ok = load_mnesia(Node), + + ?DBG("init_mnesia -> application mnesia: set_env dir: ~n~p",[Dir]), + ?line ok = set_mnesia_env(Node, dir, filename:join(Dir, "mnesia")), + + ?DBG("init_mnesia -> create mnesia schema",[]), + ?line case create_schema(Node) of + ok -> + ok; + {error, {Node, {already_exists, Node}}} -> + ?line ok = delete_schema(Node), + ?line ok = create_schema(Node); + Error -> + ?FAIL({failed_creating_mnesia_schema, Error}) + end, + + ?DBG("init_mnesia -> start application mnesia",[]), + ?line ok = start_mnesia(Node), + + ?DBG("init_mnesia -> create tables",[]), + ?line ok = create_tables(Node), + ok. + +fin_mnesia(Node) -> + ?line ok = delete_tables(Node), + ?line ok = stop_mnesia(Node), + ok. + + +init_crypto(Node) -> + ?line ok = load_crypto(Node), + ?line ok = start_crypto(Node), + ok. + +fin_crypto(Node) -> + ?line ok = stop_crypto(Node), + ok. + + +%% -- Misc application wrapper functions -- + +load_app(Node, App) when (Node =:= node()) andalso is_atom(App) -> + application:load(App); +load_app(Node, App) when is_atom(App) -> + rcall(Node, application, load, [App]). + +start_app(Node, App) when (Node =:= node()) andalso is_atom(App) -> + application:start(App); +start_app(Node, App) -> + rcall(Node, application, start, [App]). + +stop_app(Node, App) when (Node =:= node()) andalso is_atom(App) -> + application:stop(App); +stop_app(Node, App) when is_atom(App) -> + rcall(Node, application, stop, [App]). + +set_app_env(Node, App, Key, Val) when (Node =:= node()) andalso is_atom(App) -> + application:set_env(App, Key, Val); +set_app_env(Node, App, Key, Val) when is_atom(App) -> + rcall(Node, application, set_env, [App, Key, Val]). + + +%% -- Misc snmp wrapper functions -- + +load_snmp(Node) -> load_app(Node, snmp). +start_snmp(Node) -> start_app(Node, snmp). +stop_snmp(Node) -> stop_app(Node, snmp). +set_agent_env(Node, Env) -> set_snmp_env(Node, agent, Env). +set_mgr_env(Node, Env) -> set_snmp_env(Node, manager, Env). +set_snmp_env(Node, Entity, Env) -> set_app_env(Node, snmp, Entity, Env). + +mgr_info(Node) -> + rcall(Node, snmpm, info, []). + +mgr_sys_info(Node) -> + rcall(Node, snmpm_config, system_info, []). + +%% mgr_register_user(Node, Id, Data) -> +%% mgr_register_user(Node, Id, ?MODULE, Data). + +mgr_register_user(Node, Id, Mod, Data) when is_atom(Mod) -> + rcall(Node, snmpm, register_user, [Id, Mod, Data]). + +mgr_unregister_user(Node, Id) -> + rcall(Node, snmpm, unregister_user, [Id]). + +mgr_which_users(Node) -> + rcall(Node, snmpm, which_users, []). + +%% mgr_register_agent(Node, Id) -> +%% mgr_register_agent(Node, Id, []). + +%% mgr_register_agent(Node, Id, Conf) when is_list(Conf) -> +%% mgr_register_agent(Node, Id, 5000, Conf). + +mgr_register_agent(Node, Id, Port, Conf) + when is_integer(Port) andalso is_list(Conf) -> + Localhost = snmp_test_lib:localhost(), + mgr_register_agent(Node, Id, Localhost, Port, Conf); +mgr_register_agent(Node, Id, TargetName, Config) + when is_list(TargetName) andalso is_list(Config) -> + rcall(Node, snmpm, register_agent, [Id, TargetName, Config]). + +mgr_register_agent(Node, Id, Addr, Port, Conf) + when is_integer(Port) andalso is_list(Conf) -> + rcall(Node, snmpm, register_agent, [Id, Addr, Port, Conf]). + +%% mgr_unregister_agent(Node, Id) -> +%% mgr_unregister_agent(Node, Id, 4000). + +mgr_unregister_agent(Node, Id, Port) when is_integer(Port) -> + Localhost = snmp_test_lib:localhost(), + rcall(Node, snmpm, unregister_agent, [Id, Localhost, Port]); +mgr_unregister_agent(Node, Id, TargetName) when is_list(TargetName) -> + rcall(Node, snmpm, unregister_agent, [Id, TargetName]). + +mgr_which_agents(Node) -> + rcall(Node, snmpm, which_agents, []). + +mgr_which_agents(Node, Id) -> + rcall(Node, snmpm, which_agents, [Id]). + + +%% -- Misc crypto wrapper functions -- + +load_crypto(Node) -> load_app(Node, crypto). +start_crypto(Node) -> start_app(Node, crypto). +stop_crypto(Node) -> stop_app(Node, crypto). + + +%% -- Misc mnesia wrapper functions -- + +load_mnesia(Node) -> load_app(Node, mnesia). +start_mnesia(Node) -> start_app(Node, mnesia). +stop_mnesia(Node) -> stop_app(Node, mnesia). +set_mnesia_env(Node, Key, Val) -> set_app_env(Node, mnesia, Key, Val). + +create_schema(Node) -> + rcall(Node, mnesia, create_schema, [[Node]]). + +delete_schema(Node) -> + rcall(Node, mnesia, delete_schema, [[Node]]). + +create_table(Node, Table) -> + rcall(Node, mnesia, create_table, [Table]). + +delete_table(Node, Table) -> + rcall(Node, mnesia, delete_table, [Table]). + +create_tables(Node) -> + Tab1 = [{name, friendsTable2}, + {ram_copies, [Node]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}], + Tab2 = [{name, kompissTable2}, + {ram_copies, [Node]}, + {snmp, [{key, integer}]}, + {attributes, [a1,a2,a3]}], + Tab3 = [{name, snmp_variables}, + {attributes, [a1,a2]}], + Tabs = [Tab1, Tab2, Tab3], + create_tables(Node, Tabs). + +create_tables(_Node, []) -> + ok; +create_tables(Node, [Tab|Tabs]) -> + case create_table(Node, Tab) of + {atomic, ok} -> + create_tables(Node, Tabs); + Error -> + ?FAIL({failed_creating_table, Node, Tab, Error}) + end. + +delete_tables(Node) -> + Tabs = [friendsTable2, kompissTable2, snmp_variables], + delete_tables(Node, Tabs). + +%% delete_mib_storage_tables(Node) -> +%% Tabs = [snmpa_mib_data, snmpa_mib_tree, snmpa_symbolic_store], +%% delete_tables(Node, Tabs). + +delete_tables(Node, Tabs) -> + lists:foreach(fun(Tab) -> delete_table(Node, Tab) end, Tabs). + + +%% -- Misc manager user wrapper functions -- + +init_mgr_user(Conf) -> + ?DBG("init_mgr_user -> entry with" + "~n Conf: ~p", [Conf]), + + Node = ?config(manager_node, Conf), + %% UserId = ?config(user_id, Conf), + + ?line {ok, User} = mgr_user_start(Node), + ?DBG("start_mgr_user -> User: ~p", [User]), + link(User), + + [{user_pid, User} | Conf]. + +fin_mgr_user(Conf) -> + User = ?config(user_pid, Conf), + unlink(User), + Node = ?config(manager_node, Conf), + ?line ok = mgr_user_stop(Node), + Conf. + +init_mgr_user_data1(Conf) -> + Node = ?config(manager_node, Conf), + Addr = ?config(ip, Conf), + Port = ?AGENT_PORT, + ?line ok = mgr_user_register_agent(Node, Addr, Port), + Agents = mgr_user_which_own_agents(Node), + ?DBG("Own agents: ~p", [Agents]), + + ?line {ok, DefAgentConf} = mgr_user_agent_info(Node, Addr, Port, all), + ?DBG("Default agent config: ~n~p", [DefAgentConf]), + + ?line ok = mgr_user_update_agent_info(Node, Addr, Port, + community, "all-rights"), + ?line ok = mgr_user_update_agent_info(Node, Addr, Port, + sec_name, "all-rights"), + ?line ok = mgr_user_update_agent_info(Node, Addr, Port, + engine_id, "agentEngine"), + ?line ok = mgr_user_update_agent_info(Node, Addr, Port, + max_message_size, 1024), + + ?line {ok, AgentConf} = mgr_user_agent_info(Node, Addr, Port, all), + ?DBG("Updated agent config: ~n~p", [AgentConf]), + Conf. + +init_mgr_user_data2(Conf) -> + Node = ?config(manager_node, Conf), + TargetName = ?config(manager_agent_target_name, Conf), + Addr = ?config(ip, Conf), + Port = ?AGENT_PORT, + ?line ok = mgr_user_register_agent(Node, TargetName, + [{address, Addr}, + {port, Port}, + {engine_id, "agentEngine"}]), + Agents = mgr_user_which_own_agents(Node), + ?DBG("Own agents: ~p", [Agents]), + + ?line {ok, DefAgentConf} = mgr_user_agent_info(Node, TargetName, all), + ?DBG("Default agent config: ~n~p", [DefAgentConf]), + + ?line ok = mgr_user_update_agent_info(Node, TargetName, + community, "all-rights"), + ?line ok = mgr_user_update_agent_info(Node, TargetName, + sec_name, "all-rights"), + ?line ok = mgr_user_update_agent_info(Node, TargetName, + max_message_size, 1024), + + ?line {ok, AgentConf} = mgr_user_agent_info(Node, TargetName, all), + ?DBG("Updated agent config: ~n~p", [AgentConf]), + Conf. + +fin_mgr_user_data1(Conf) -> + Node = ?config(manager_node, Conf), + Addr = ?config(ip, Conf), + Port = ?AGENT_PORT, + mgr_user_unregister_agent(Node, Addr, Port), + mgr_user_which_own_agents(Node), + Conf. + +fin_mgr_user_data2(Conf) -> + Node = ?config(manager_node, Conf), + TargetName = ?config(manager_agent_target_name, Conf), + mgr_user_unregister_agent(Node, TargetName), + mgr_user_which_own_agents(Node), + Conf. + +mgr_user_start(Node) -> + mgr_user_start(Node, snmp_manager_test_user). +mgr_user_start(Node, Id) -> + rcall(Node, snmp_manager_user, start, [self(), Id]). + +mgr_user_stop(Node) -> + rcall(Node, snmp_manager_user, stop, []). + +%% mgr_user_register_agent(Node) -> +%% mgr_user_register_agent(Node, ?LOCALHOST(), ?AGENT_PORT, []). +%% mgr_user_register_agent(Node, TargetName) when is_list(TargetName) -> +%% mgr_user_register_agent(Node, TargetName, []); +%% mgr_user_register_agent(Node, Addr) -> +%% mgr_user_register_agent(Node, Addr, ?AGENT_PORT, []). +mgr_user_register_agent(Node, TargetName, Conf) + when is_list(TargetName) andalso is_list(Conf) -> + rcall(Node, snmp_manager_user, register_agent, [TargetName, Conf]); +mgr_user_register_agent(Node, Addr, Port) -> + mgr_user_register_agent(Node, Addr, Port, []). +mgr_user_register_agent(Node, Addr, Port, Conf) -> + rcall(Node, snmp_manager_user, register_agent, [Addr, Port, Conf]). + +%% mgr_user_unregister_agent(Node) -> +%% mgr_user_unregister_agent(Node, ?LOCALHOST(), ?AGENT_PORT). +mgr_user_unregister_agent(Node, Addr_or_TargetName) -> + rcall(Node, snmp_manager_user, unregister_agent, [Addr_or_TargetName]). +mgr_user_unregister_agent(Node, Addr, Port) -> + rcall(Node, snmp_manager_user, unregister_agent, [Addr, Port]). + +mgr_user_agent_info(Node, Addr_or_TargetName, Item) when is_atom(Item) -> + rcall(Node, snmp_manager_user, agent_info, [Addr_or_TargetName, Item]). +mgr_user_agent_info(Node, Addr, Port, Item) when is_atom(Item) -> + rcall(Node, snmp_manager_user, agent_info, [Addr, Port, Item]). + +%% mgr_user_update_agent_info(Node, Item, Val) when atom(Item) -> +%% mgr_user_update_agent_info(Node, ?LOCALHOST(), ?AGENT_PORT, Item, Val). +mgr_user_update_agent_info(Node, Addr_or_TargetName, Item, Val) + when is_atom(Item) -> + rcall(Node, snmp_manager_user, update_agent_info, + [Addr_or_TargetName, Item, Val]). +mgr_user_update_agent_info(Node, Addr, Port, Item, Val) when is_atom(Item) -> + rcall(Node, snmp_manager_user, update_agent_info, + [Addr, Port, Item, Val]). + +%% mgr_user_which_all_agents(Node) -> +%% rcall(Node, snmp_manager_user, which_all_agents, []). + +mgr_user_which_own_agents(Node) -> + rcall(Node, snmp_manager_user, which_own_agents, []). + +mgr_user_load_mib(Node, Mib) -> + rcall(Node, snmp_manager_user, load_mib, [Mib]). + +%% mgr_user_sync_get(Node, Oids) -> +%% mgr_user_sync_get(Node, ?LOCALHOST(), ?AGENT_PORT, Oids). +mgr_user_sync_get(Node, Addr_or_TargetName, Oids) -> + rcall(Node, snmp_manager_user, sync_get, [Addr_or_TargetName, Oids]). +mgr_user_sync_get(Node, Addr, Port, Oids) -> + rcall(Node, snmp_manager_user, sync_get, [Addr, Port, Oids]). + +%% mgr_user_async_get(Node, Oids) -> +%% mgr_user_async_get(Node, ?LOCALHOST(), ?AGENT_PORT, Oids). +mgr_user_async_get(Node, Addr_or_TargetName, Oids) -> + rcall(Node, snmp_manager_user, async_get, [Addr_or_TargetName, Oids]). +mgr_user_async_get(Node, Addr, Port, Oids) -> + rcall(Node, snmp_manager_user, async_get, [Addr, Port, Oids]). + +%% mgr_user_sync_get_next(Node, Oids) -> +%% mgr_user_sync_get_next(Node, ?LOCALHOST(), ?AGENT_PORT, Oids). +mgr_user_sync_get_next(Node, Addr_or_TargetName, Oids) -> + rcall(Node, snmp_manager_user, sync_get_next, [Addr_or_TargetName, Oids]). +mgr_user_sync_get_next(Node, Addr, Port, Oids) -> + rcall(Node, snmp_manager_user, sync_get_next, [Addr, Port, Oids]). + +%% mgr_user_async_get_next(Node, Oids) -> +%% mgr_user_async_get_next(Node, ?LOCALHOST(), ?AGENT_PORT, Oids). +mgr_user_async_get_next(Node, Addr_or_TargetName, Oids) -> + rcall(Node, snmp_manager_user, async_get_next, [Addr_or_TargetName, Oids]). +mgr_user_async_get_next(Node, Addr, Port, Oids) -> + rcall(Node, snmp_manager_user, async_get_next, [Addr, Port, Oids]). + +%% mgr_user_sync_set(Node, VAV) -> +%% mgr_user_sync_set(Node, ?LOCALHOST(), ?AGENT_PORT, VAV). +mgr_user_sync_set(Node, Addr_or_TargetName, VAV) -> + rcall(Node, snmp_manager_user, sync_set, [Addr_or_TargetName, VAV]). +mgr_user_sync_set(Node, Addr, Port, VAV) -> + rcall(Node, snmp_manager_user, sync_set, [Addr, Port, VAV]). + +%% mgr_user_async_set(Node, VAV) -> +%% mgr_user_async_set(Node, ?LOCALHOST(), ?AGENT_PORT, VAV). +mgr_user_async_set(Node, Addr_or_TargetName, VAV) -> + rcall(Node, snmp_manager_user, async_set, [Addr_or_TargetName, VAV]). +mgr_user_async_set(Node, Addr, Port, VAV) -> + rcall(Node, snmp_manager_user, async_set, [Addr, Port, VAV]). + +%% mgr_user_sync_get_bulk(Node, NonRep, MaxRep, Oids) -> +%% mgr_user_sync_get_bulk(Node, ?LOCALHOST(), ?AGENT_PORT, +%% NonRep, MaxRep, Oids). +mgr_user_sync_get_bulk(Node, Addr_or_TargetName, NonRep, MaxRep, Oids) -> + rcall(Node, snmp_manager_user, sync_get_bulk, + [Addr_or_TargetName, NonRep, MaxRep, Oids]). +mgr_user_sync_get_bulk(Node, Addr, Port, NonRep, MaxRep, Oids) -> + rcall(Node, snmp_manager_user, sync_get_bulk, + [Addr, Port, NonRep, MaxRep, Oids]). + +%% mgr_user_async_get_bulk(Node, NonRep, MaxRep, Oids) -> +%% mgr_user_async_get_bulk(Node, ?LOCALHOST(), ?AGENT_PORT, +%% NonRep, MaxRep, Oids). +mgr_user_async_get_bulk(Node, Addr_or_TargetName, NonRep, MaxRep, Oids) -> + rcall(Node, snmp_manager_user, async_get_bulk, + [Addr_or_TargetName, NonRep, MaxRep, Oids]). +mgr_user_async_get_bulk(Node, Addr, Port, NonRep, MaxRep, Oids) -> + rcall(Node, snmp_manager_user, async_get_bulk, + [Addr, Port, NonRep, MaxRep, Oids]). + +mgr_user_purify_oid(Node, Oid) -> + rcall(Node, snmp_manager_user, purify_oid, [Oid]). + +mgr_user_name_to_oid(Node, Name) -> + rcall(Node, snmp_manager_user, name_to_oid, [Name]). + + +%% -- Misc manager wrapper functions -- + +start_manager(Node, Vsns, Config) -> + start_manager(Node, Vsns, Config, []). +start_manager(Node, Vsns, Conf0, Opts) -> + ?DBG("start_manager -> entry with" + "~n Node: ~p" + "~n Vsns: ~p" + "~n Conf0: ~p" + "~n Opts: ~p", [Node, Vsns, Conf0, Opts]), + + AtlDir = ?config(manager_log_dir, Conf0), + ConfDir = ?config(manager_conf_dir, Conf0), + DbDir = ?config(manager_db_dir, Conf0), + IRB = ?config(irb, Conf0), + + ConfigVerbosity = get_opt(manager_config_verbosity, Conf0, trace), + NoteStoreVerbosity = get_opt(manager_note_store_verbosity, Conf0, log), + ServerVerbosity = get_opt(manager_server_verbosity, Conf0, trace), + NetIfVerbosity = get_opt(manager_net_if_verbosity, Conf0, trace), + + Env = [{versions, Vsns}, + {inform_request_behaviour, IRB}, + {audit_trail_log, [{type, read_write}, + {dir, AtlDir}, + {size, {10240, 10}}, + {repair, true}]}, + {config, [{dir, ConfDir}, + {db_dir, DbDir}, + {verbosity, ConfigVerbosity}]}, + {note_store, [{verbosity, NoteStoreVerbosity}]}, + {server, [{verbosity, ServerVerbosity}]}, + {net_if, [{verbosity, NetIfVerbosity}]}], + ?line ok = set_mgr_env(Node, Env), + + ?line ok = start_snmp(Node), + + Conf0. + +stop_manager(Node, Conf) -> + stop_snmp(Node), + Conf. + +%% -- Misc agent wrapper functions -- + +start_agent(Node, Vsns, Config) -> + start_agent(Node, Vsns, Config, []). +start_agent(Node, Vsns, Conf0, Opts) -> + ?DBG("start_agent -> entry with" + "~n Node: ~p" + "~n Vsns: ~p" + "~n Conf0: ~p" + "~n Opts: ~p", [Node, Vsns, Conf0, Opts]), + + AtlDir = ?config(agent_log_dir, Conf0), + ConfDir = ?config(agent_conf_dir, Conf0), + DbDir = ?config(agent_db_dir, Conf0), + + MAV = get_opt(agent_verbosity, Conf0, trace), + CV = get_opt(agent_config_verbosity, Conf0, info), + LDBV = get_opt(agent_local_db_verbosity, Conf0, info), + MSV = get_opt(agent_mib_server_verbosity, Conf0, info), + NSV = get_opt(agent_note_store_verbosity, Conf0, info), + SSV = get_opt(agent_symbolic_store_verbosity, Conf0, info), + NIV = get_opt(agent_net_if_verbosity, Conf0, log), + + Env = [{versions, Vsns}, + {type, master}, + {agent_verbosity, MAV}, + {audit_trail_log, [{type, read_write}, + {dir, AtlDir}, + {size, {10240, 10}}, + {repair, true}]}, + {config, [{dir, ConfDir}, + {force_load, false}, + {verbosity, CV}]}, + {db_dir, DbDir}, + {local_db, [{repair, true}, + {auto_save, 10000}, + {verbosity, LDBV}]}, + {mib_server, [{verbosity, MSV}]}, + {note_store, [{verbosity, NSV}]}, + {stymbolic_store, [{verbosity, SSV}]}, + {net_if, [{verbosity, NIV}]}, + {multi_threaded, true}], + ?line ok = set_agent_env(Node, Env), + + ?line ok = start_snmp(Node), + Conf0. + +stop_agent(Node, Conf) -> + stop_snmp(Node), + Conf. + +agent_load_mib(Node, Mib) -> + rcall(Node, snmpa, load_mibs, [[Mib]]). +%% agent_unload_mib(Node, Mib) -> +%% rcall(Node, snmpa, unload_mibs, [[Mib]]). + +%% agent_send_trap(Node, Trap, Community) -> +%% Args = [snmp_master_agent, Trap, Community], +%% rcall(Node, snmpa, send_trap, Args). + +agent_send_trap(Node, Trap, Community, VBs) -> + Args = [snmp_master_agent, Trap, Community, VBs], + rcall(Node, snmpa, send_trap, Args). + +agent_send_notif(Node, Trap, Name) -> + agent_send_notif(Node, Trap, Name, []). + +agent_send_notif(Node, Trap, Name, VBs) -> + agent_send_notif(Node, Trap, no_receiver, Name, VBs). + +agent_send_notif(Node, Trap, Recv, Name, VBs) -> + Args = [snmp_master_agent, Trap, Recv, Name, VBs], + rcall(Node, snmpa, send_notification, Args). + +agent_info(Node) -> + rcall(Node, snmpa, info, []). + +%% agent_which_mibs(Node) -> +%% rcall(Node, snmpa, which_mibs, []). + + +%% -- Misc node operation wrapper functions -- + +start_agent_node() -> + start_node(snmp_agent). + +start_manager_node() -> + start_node(snmp_manager). + +start_node(Name) -> + Pa = filename:dirname(code:which(?MODULE)), + Args = case init:get_argument('CC_TEST') of + {ok, [[]]} -> + " -pa /clearcase/otp/libraries/snmp/ebin "; + {ok, [[Path]]} -> + " -pa " ++ Path; + error -> + "" + end, + A = Args ++ " -pa " ++ Pa, + case (catch ?START_NODE(Name, A)) of + {ok, Node} -> + Node; + Else -> + ?line ?FAIL(Else) + end. + +stop_node(Node) -> + rpc:cast(Node, erlang, halt, []), + await_stopped(Node, 5). + +await_stopped(_, 0) -> + ok; +await_stopped(Node, N) -> + Nodes = erlang:nodes(), + case lists:member(Node, Nodes) of + true -> + ?DBG("[~w] ~p still exist", [N, Node]), + ?SLEEP(1000), + await_stopped(Node, N-1); + false -> + ?DBG("[~w] ~p gone", [N, Node]), + ok + end. + + + +%% -- Misc config wrapper functions -- + +write_manager_config(Config) -> + Dir = ?config(manager_conf_dir, Config), + Ip = ?config(ip, Config), + Addr = tuple_to_list(Ip), + snmp_config:write_manager_snmp_files(Dir, Addr, ?MGR_PORT, + ?MGR_MMS, ?MGR_ENGINE_ID, [], [], []). + +write_manager_conf(Dir) -> + Port = "5000", + MMS = "484", + EngineID = "\"mgrEngine\"", + Str = lists:flatten( + io_lib:format("%% Minimum manager config file\n" + "{port, ~s}.\n" + "{max_message_size, ~s}.\n" + "{engine_id, ~s}.\n", + [Port, MMS, EngineID])), + write_manager_conf(Dir, Str). + +%% write_manager_conf(Dir, IP, Port, MMS, EngineID) -> +%% Str = lists:flatten( +%% io_lib:format("{address, ~s}.\n" +%% "{port, ~s}.\n" +%% "{max_message_size, ~s}.\n" +%% "{engine_id, ~s}.\n", +%% [IP, Port, MMS, EngineID])), +%% write_manager_conf(Dir, Str). + +write_manager_conf(Dir, Str) -> + write_conf_file(Dir, "manager.conf", Str). + + +write_agent_config(Vsns, Conf) -> + Dir = ?config(agent_conf_dir, Conf), + Ip = ?config(ip, Conf), + ?line Addr = tuple_to_list(Ip), + ?line ok = write_agent_config_files(Dir, Vsns, Addr), + ?line ok = update_agent_usm(Vsns, Dir), + ?line ok = update_agent_community(Vsns, Dir), + ?line ok = update_agent_vacm(Vsns, Dir), + ?line ok = write_agent_target_addr_conf(Dir, Addr, Vsns), + ?line ok = write_agent_target_params_conf(Dir, Vsns), + ?line ok = write_agent_notify_conf(Dir), + ok. + +write_agent_config_files(Dir, Vsns, Addr) -> + snmp_config:write_agent_snmp_files(Dir, Vsns, + Addr, ?MGR_PORT, + Addr, ?AGENT_PORT, + "mgr-test", "trap", + none, "", + ?AGENT_ENGINE_ID, + ?AGENT_MMS). + +update_agent_usm(Vsns, Dir) -> + case lists:member(v3, Vsns) of + true -> + Conf = [{"agentEngine", "all-rights", "all-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"agentEngine", "no-rights", "no-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"agentEngine", "authMD5", "authMD5", zeroDotZero, + usmHMACMD5AuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "passwd_md5xxxxxx", ""}, + + {"agentEngine", "authSHA", "authSHA", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", ""}, + + {"agentEngine", "privDES", "privDES", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}, + + {"mgrEngine", "all-rights", "all-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"mgrEngine", "no-rights", "no-rights", zeroDotZero, + usmNoAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "", ""}, + + {"mgrEngine", "authMD5", "authMD5", zeroDotZero, + usmHMACMD5AuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", "passwd_md5xxxxxx", ""}, + + {"mgrEngine", "authSHA", "authSHA", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmNoPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", ""}, + + {"mgrEngine", "privDES", "privDES", zeroDotZero, + usmHMACSHAAuthProtocol, "", "", + usmDESPrivProtocol, "", "", "", + "passwd_shaxxxxxxxxxx", "passwd_desxxxxxx"}], + snmp_config:update_agent_usm_config(Dir, Conf); + false -> + ok + end. + +update_agent_community([v3], _Dir) -> + ok; +update_agent_community(_, Dir) -> + Conf = [{"no-rights", "no-rights", "no-rights", "", ""}], + snmp_config:update_agent_community_config(Dir, Conf). + +update_agent_vacm(_Vsns, Dir) -> + Conf = [{vacmSecurityToGroup, usm, "authMD5", "initial"}, + {vacmSecurityToGroup, usm, "authSHA", "initial"}, + {vacmSecurityToGroup, usm, "privDES", "initial"}, + {vacmSecurityToGroup, usm, "newUser", "initial"}, + {vacmViewTreeFamily, "internet", ?tDescr_instance, + excluded, null}], + snmp_config:update_agent_vacm_config(Dir, Conf). + +write_agent_target_addr_conf(Dir, Addr, Vsns) -> + snmp_config:write_agent_snmp_target_addr_conf(Dir, Addr, ?MGR_PORT, + 300, 3, Vsns). + +write_agent_target_params_conf(Dir, Vsns) -> + F = fun(v1) -> {"target_v1", v1, v1, "all-rights", noAuthNoPriv}; + (v2) -> {"target_v2", v2c, v2c, "all-rights", noAuthNoPriv}; + (v3) -> {"target_v3", v3, usm, "all-rights", noAuthNoPriv} + end, + Conf = [F(Vsn) || Vsn <- Vsns], + snmp_config:write_agent_target_params_config(Dir, "", Conf). + +write_agent_notify_conf(Dir) -> + Conf = [{"standard trap", "std_trap", trap}, + {"standard inform", "std_inform", inform}], + snmp_config:write_agent_notify_config(Dir, "", Conf). + + +write_conf_file(Dir, File, Str) -> + ?line {ok, Fd} = file:open(filename:join(Dir, File), write), + ?line ok = io:format(Fd, "~s", [Str]), + file:close(Fd). + + +%% ------ + +test2_mib(Config) -> + j(test_mib_dir(Config), "Test2.bin"). + +test_trap_mib(Config) -> + j(test_mib_dir(Config), "TestTrap.bin"). + +test_trap_v2_mib(Config) -> + j(test_mib_dir(Config), "TestTrapv2.bin"). + +std_mib() -> + j(mib_dir(), "STANDARD-MIB.bin"). + +snmpv2_mib() -> + j(mib_dir(), "SNMPv2-MIB.bin"). + +test_mib_dir(Config) -> + ?config(snmp_data_dir, Config). + +mib_dir() -> + j(code:priv_dir(snmp), "mibs"). + +j(A, B) -> + filename:join(A, B). + + +%% ------ + +get_opt(Key, Opts, Def) -> + snmp_misc:get_option(Key, Opts, Def). + + +%% ------ + +rcall(Node, Mod, Func, Args) -> + case rpc:call(Node, Mod, Func, Args) of + {badrpc, nodedown} -> + ?FAIL({rpc_failure, Node}); + Else -> + Else + end. + + +%% ------ + +%% Time in milli sec +%% t() -> +%% {A,B,C} = erlang:now(), +%% A*1000000000+B*1000+(C div 1000). + + +%% ------ + +p(F) -> + p(F, []). + +p(F, A) -> + p(get(tname), F, A). + +p(TName, F, A) -> + io:format("*** [~w][~s] ***" + "~n" ++ F ++ "~n", [TName,format_timestamp(now())|A]). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + +%% p(TName, F, A) -> +%% io:format("~w -> " ++ F ++ "~n", [TName|A]). + diff --git a/lib/snmp/test/snmp_manager_user.erl b/lib/snmp/test/snmp_manager_user.erl new file mode 100644 index 0000000000..07b56bde39 --- /dev/null +++ b/lib/snmp/test/snmp_manager_user.erl @@ -0,0 +1,935 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Utility functions for the (snmp manager) user test(s). +%%---------------------------------------------------------------------- + +-module(snmp_manager_user). + +-behaviour(snmpm_user). +%% -behaviour(snmpm_user_old). + + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + start_link/0, start_link/1, start_link/2, + start/0, start/1, start/2, + stop/0, + info/0, + system_info/0, + simulate_crash/1, + register_agent/2, register_agent/3, + unregister_agent/1, unregister_agent/2, + agent_info/2, agent_info/3, + update_agent_info/3, update_agent_info/4, + which_all_agents/0, which_own_agents/0, + load_mib/1, unload_mib/1, + sync_get/1, sync_get/2, sync_get/3, + async_get/1, async_get/2, async_get/3, + sync_get_next/1, sync_get_next/2, sync_get_next/3, + async_get_next/1, async_get_next/2, async_get_next/3, + sync_set/1, sync_set/2, sync_set/3, + async_set/1, async_set/2, async_set/3, + sync_get_bulk/3, sync_get_bulk/4, sync_get_bulk/5, + async_get_bulk/3, async_get_bulk/4, async_get_bulk/5, + name_to_oid/1, oid_to_name/1, + purify_oid/1 + ]). + + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- + +-export([ + main/4 + ]). + +-export([ + handle_error/3, + handle_agent/4, + handle_pdu/4, + handle_trap/3, + handle_inform/3, + handle_report/3, + handle_pdu/5, % For backwards compatibillity + handle_trap/4, % For backwards compatibillity + handle_inform/4, % For backwards compatibillity + handle_report/4 % For backwards compatibillity + ]). + + +-define(SERVER, ?MODULE). + +-record(state, {parent, id, reqs = []}). +%% -record(request, {from, ref, tmr, req_id, type}). + + +%%---------------------------------------------------------------------- +%% The user API +%%---------------------------------------------------------------------- + +start() -> + start(self()). + +start(Parent) -> + start(Parent, test_user). + +start(Parent, Id) -> + proc_lib:start(?MODULE, main, [true, Parent, self(), Id]). + +start_link() -> + start_link(self()). +start_link(Parent) -> + start_link(Parent, test_user). + +start_link(Parent, Id) -> + proc_lib:start_link(?MODULE, main, [true, Parent, self(), Id]). + +stop() -> + cast(stop). + +info() -> + call(info). + +system_info() -> + call(system_info). + +simulate_crash(Reason) -> + call({simulate_crash, Reason}). + +register_agent(TargetName, Config) + when is_list(TargetName) andalso is_list(Config) -> + call({register_agent, TargetName, Config}); +register_agent(Addr, Port) -> + register_agent(Addr, Port, []). + +register_agent(Addr, Port, Conf) -> + call({register_agent, Addr, Port, Conf}). + +unregister_agent(TargetName) -> + call({unregister_agent, TargetName}). +unregister_agent(Addr, Port) -> + call({unregister_agent, Addr, Port}). + +agent_info(TargetName, Item) -> + call({agent_info, TargetName, Item}). +agent_info(Addr, Port, Item) -> + call({agent_info, Addr, Port, Item}). + +update_agent_info(TargetName, Item, Val) -> + call({update_agent_info, TargetName, Item, Val}). +update_agent_info(Addr, Port, Item, Val) -> + call({update_agent_info, Addr, Port, Item, Val}). + +which_all_agents() -> + call(which_all_agents). + +which_own_agents() -> + call(which_own_agents). + +load_mib(Mib) -> + call({load_mib, Mib}). + +unload_mib(Mib) -> + call({unload_mib, Mib}). + +%% -- + +sync_get(Oids) -> + call({sync_get, Oids}). + +sync_get(Addr_or_TargetName, Oids) -> + call({sync_get, Addr_or_TargetName, Oids}). + +sync_get(Addr, Port, Oids) -> + call({sync_get, Addr, Port, Oids}). + +%% -- + +async_get(Oids) -> + call({async_get, Oids}). + +async_get(Addr_or_TargetName, Oids) -> + call({async_get, Addr_or_TargetName, Oids}). + +async_get(Addr, Port, Oids) -> + call({async_get, Addr, Port, Oids}). + +%% -- + +sync_get_next(Oids) -> + call({sync_get_next, Oids}). + +sync_get_next(Addr_or_TargetName, Oids) -> + call({sync_get_next, Addr_or_TargetName, Oids}). + +sync_get_next(Addr, Port, Oids) -> + call({sync_get_next, Addr, Port, Oids}). + +%% -- + +async_get_next(Oids) -> + call({async_get_next, Oids}). + +async_get_next(Addr_or_TargetName, Oids) -> + call({async_get_next, Addr_or_TargetName, Oids}). + +async_get_next(Addr, Port, Oids) -> + call({async_get_next, Addr, Port, Oids}). + +%% -- + +sync_set(VAV) -> + call({sync_set, VAV}). + +sync_set(Addr_or_TargetName, VAV) -> + call({sync_set, Addr_or_TargetName, VAV}). + +sync_set(Addr, Port, VAV) -> + call({sync_set, Addr, Port, VAV}). + +%% -- + +async_set(VAV) -> + call({async_set, VAV}). + +async_set(Addr_or_TargetName, VAV) -> + call({async_set, Addr_or_TargetName, VAV}). + +async_set(Addr, Port, VAV) -> + call({async_set, Addr, Port, VAV}). + +%% -- + +sync_get_bulk(NonRep, MaxRep, Oids) -> + call({sync_get_bulk, NonRep, MaxRep, Oids}). + +sync_get_bulk(Addr_or_TargetName, NonRep, MaxRep, Oids) -> + call({sync_get_bulk, Addr_or_TargetName, NonRep, MaxRep, Oids}). + +sync_get_bulk(Addr, Port, NonRep, MaxRep, Oids) -> + call({sync_get_bulk, Addr, Port, NonRep, MaxRep, Oids}). + +%% -- + +async_get_bulk(NonRep, MaxRep, Oids) -> + call({async_get_bulk, NonRep, MaxRep, Oids}). + +async_get_bulk(Addr_or_TargetName, NonRep, MaxRep, Oids) -> + call({async_get_bulk, Addr_or_TargetName, NonRep, MaxRep, Oids}). + +async_get_bulk(Addr, Port, NonRep, MaxRep, Oids) -> + call({async_get_bulk, Addr, Port, NonRep, MaxRep, Oids}). + +%% -- + +name_to_oid(Name) -> + call({name_to_oid, Name}). + +oid_to_name(Oid) -> + call({oid_to_name, Oid}). + +purify_oid(Oid) -> + call({purify_oid, Oid}). + + +%%---------------------------------------------------------------------- + +main(Debug, Parent, Starter, Id) -> + put(debug, Debug), + d("main -> entry with" + "~n Parent: ~p" + "~n Starter: ~p" + "~n Id: ~p", [Parent, Starter, Id]), + case (catch do_init(Id)) of + ok -> + proc_lib:init_ack(Starter, {ok, self()}), + loop(#state{parent = Parent, id = Id}); + Error -> + d("main -> error: " + "~p", [Error]), + proc_lib:init_ack(Starter, Error) + end. + +do_init(Id) -> + erlang:register(?SERVER, self()), + snmpm:register_user(Id, ?MODULE, self()). + + +%%---------------------------------------------------------------------- + +loop(#state{parent = Parent, id = Id} = S) -> + d("loop -> entry"), + receive + {stop, _From} -> + d("loop -> received stop request"), + exit(normal); + + {{simulate_crash, Reason}, From, Ref} -> + d("loop -> received simulate_crash request"), + reply(From, ok, Ref), + exit(Reason); + + {info, From, Ref} -> + d("loop -> received info request"), + Res = snmpm:info(), + reply(From, Res, Ref), + loop(S); + + {system_info, From, Ref} -> + d("loop -> received system_info request"), + Res = snmpm_config:system_info(), + reply(From, Res, Ref), + loop(S); + + {{register_agent, TargetName, Conf}, From, Ref} -> + d("loop -> received register_agent request"), + Res = snmpm:register_agent(Id, TargetName, Conf), + reply(From, Res, Ref), + loop(S); + + {{register_agent, Addr, Port, Conf}, From, Ref} -> + d("loop -> received register_agent request"), + Res = snmpm:register_agent(Id, Addr, Port, Conf), + reply(From, Res, Ref), + loop(S); + + {{unregister_agent, TargetName}, From, Ref} -> + d("loop -> received unregister_agent request"), + Res = snmpm:unregister_agent(Id, TargetName), + reply(From, Res, Ref), + loop(S); + + {{unregister_agent, Addr, Port}, From, Ref} -> + d("loop -> received unregister_agent request"), + Res = snmpm:unregister_agent(Id, Addr, Port), + reply(From, Res, Ref), + loop(S); + + {{agent_info, TargetName, Item}, From, Ref} -> + d("loop -> received agent_info request with" + "~n TargetName: ~p" + "~n Item: ~p", [TargetName, Item]), + Res = snmpm:agent_info(TargetName, Item), + d("loop -> agent_info for ~p" + "~n Res: ~p", [Item, Res]), + reply(From, Res, Ref), + loop(S); + + {{agent_info, Addr, Port, Item}, From, Ref} -> + d("loop -> received agent_info request with" + "~n Addr: ~p" + "~n Port: ~p" + "~n Item: ~p", [Addr, Port, Item]), + Res = snmpm:agent_info(Addr, Port, Item), + reply(From, Res, Ref), + loop(S); + + {{update_agent_info, TargetName, Item, Val}, From, Ref} -> + d("loop -> received update_agent_info request with" + "~n TargetName: ~p" + "~n Item: ~p" + "~n Val: ~p", [TargetName, Item, Val]), + Res = snmpm:update_agent_info(Id, TargetName, Item, Val), + reply(From, Res, Ref), + loop(S); + + {{update_agent_info, Addr, Port, Item, Val}, From, Ref} -> + d("loop -> received update_agent_info request with" + "~n Addr: ~p" + "~n Port: ~p" + "~n Item: ~p" + "~n Val: ~p", [Addr, Port, Item, Val]), + Res = snmpm:update_agent_info(Id, Addr, Port, Item, Val), + reply(From, Res, Ref), + loop(S); + + {which_all_agents, From, Ref} -> + d("loop -> received which_all_agents request"), + Res = snmpm:which_agents(), + reply(From, Res, Ref), + loop(S); + + {which_own_agents, From, Ref} -> + d("loop -> received which_own_agents request"), + Res = snmpm:which_agents(Id), + reply(From, Res, Ref), + loop(S); + + {{load_mib, Mib}, From, Ref} -> + d("loop -> received load_mib request"), + Res = snmpm:load_mib(Mib), + reply(From, Res, Ref), + loop(S); + + {{unload_mib, Mib}, From, Ref} -> + d("loop -> received unload_mib request"), + Res = snmpm:unload_mib(Mib), + reply(From, Res, Ref), + loop(S); + + + %% + %% -- (sync) get-request -- + %% + + %% No agent specified, so send it to all of them + {{sync_get, Oids}, From, Ref} -> + d("loop -> received sync_get request " + "(for every agent of this user)"), + Res = [snmpm:sync_get(Id, TargetName, Oids) || + TargetName <- snmpm:which_agents(Id)], + reply(From, Res, Ref), + loop(S); + + {{sync_get, TargetName, Oids}, From, Ref} when is_list(TargetName) -> + d("loop -> received sync_get request with" + "~n TargetName: ~p" + "~n Oids: ~p", [TargetName, Oids]), + Res = snmpm:sync_get(Id, TargetName, Oids), + reply(From, Res, Ref), + loop(S); + + {{sync_get, Addr, Oids}, From, Ref} -> + d("loop -> received sync_get request with" + "~n Addr: ~p" + "~n Oids: ~p", [Addr, Oids]), + Res = snmpm:g(Id, Addr, Oids), + reply(From, Res, Ref), + loop(S); + + {{sync_get, Addr, Port, Oids}, From, Ref} -> + d("loop -> received sync_get request with" + "~n Addr: ~p" + "~n Port: ~p" + "~n Oids: ~p", [Addr, Port, Oids]), + Res = snmpm:g(Id, Addr, Port, Oids), + reply(From, Res, Ref), + loop(S); + + + %% + %% -- (async) get-request -- + %% + + %% No agent specified, so send it to all of them + {{async_get, Oids}, From, Ref} -> + d("loop -> received async_get request"), + Res = [snmpm:async_get(Id, TargetName, Oids) || + TargetName <- snmpm:which_agents(Id)], + reply(From, Res, Ref), + loop(S); + + {{async_get, TargetName, Oids}, From, Ref} when is_list(TargetName) -> + d("loop -> received async_get request with" + "~n TargetName: ~p" + "~n Oids: ~p", [TargetName, Oids]), + Res = snmpm:async_get(Id, TargetName, Oids), + reply(From, Res, Ref), + loop(S); + + {{async_get, Addr, Oids}, From, Ref} -> + d("loop -> received async_get request"), + Res = snmpm:ag(Id, Addr, Oids), + reply(From, Res, Ref), + loop(S); + + {{async_get, Addr, Port, Oids}, From, Ref} -> + d("loop -> received async_get request"), + Res = snmpm:ag(Id, Addr, Port, Oids), + reply(From, Res, Ref), + loop(S); + + + %% + %% -- (sync) get_next-request -- + %% + + %% No agent specified, so send it to all of them + {{sync_get_next, Oids}, From, Ref} -> + d("loop -> received sync_get_next request"), + Res = [snmpm:sync_get_next(Id, TargetName, Oids) || + TargetName <- snmpm:which_agents(Id)], + reply(From, Res, Ref), + loop(S); + + {{sync_get_next, TargetName, Oids}, From, Ref} when is_list(TargetName) -> + d("loop -> received sync_get_next request with" + "~n TargetName: ~p" + "~n Oids: ~p", [TargetName, Oids]), + Res = snmpm:sync_get_next(Id, TargetName, Oids), + reply(From, Res, Ref), + loop(S); + + {{sync_get_next, Addr, Oids}, From, Ref} -> + d("loop -> received sync_get_next request"), + Res = snmpm:gn(Id, Addr, Oids), + reply(From, Res, Ref), + loop(S); + + {{sync_get_next, Addr, Port, Oids}, From, Ref} -> + d("loop -> received sync_get_next request"), + Res = snmpm:gn(Id, Addr, Port, Oids), + reply(From, Res, Ref), + loop(S); + + + %% + %% -- (async) get_next-request -- + %% + + %% No agent specified, so send it to all of them + {{async_get_next, Oids}, From, Ref} -> + d("loop -> received async_get_next request"), + Res = [snmpm:async_get_next(Id, TargetName, Oids) || + TargetName <- snmpm:which_agents(Id)], + reply(From, Res, Ref), + loop(S); + + {{async_get_next, TargetName, Oids}, From, Ref} when is_list(TargetName) -> + d("loop -> received async_get_next request with" + "~n TargetName: ~p" + "~n Oids: ~p", [TargetName, Oids]), + Res = snmpm:async_get_next(Id, TargetName, Oids), + reply(From, Res, Ref), + loop(S); + + {{async_get_next, Addr, Oids}, From, Ref} -> + d("loop -> received async_get_next request"), + Res = snmpm:agn(Id, Addr, Oids), + reply(From, Res, Ref), + loop(S); + + {{async_get_next, Addr, Port, Oids}, From, Ref} -> + d("loop -> received async_get_next request"), + Res = snmpm:agn(Id, Addr, Port, Oids), + reply(From, Res, Ref), + loop(S); + + + %% + %% -- (sync) set-request -- + %% + + {{sync_set, VAV}, From, Ref} -> + d("loop -> received sync_set request"), + Res = [snmpm:sync_set(Id, TargetName, VAV) || + TargetName <- snmpm:which_agents(Id)], + reply(From, Res, Ref), + loop(S); + + {{sync_set, TargetName, VAV}, From, Ref} when is_list(TargetName) -> + d("loop -> received sync_set request"), + Res = snmpm:sync_set(Id, TargetName, VAV), + reply(From, Res, Ref), + loop(S); + + {{sync_set, Addr, VAV}, From, Ref} -> + d("loop -> received sync_set request"), + Res = snmpm:s(Id, Addr, VAV), + reply(From, Res, Ref), + loop(S); + + {{sync_set, Addr, Port, VAV}, From, Ref} -> + d("loop -> received sync_set request"), + Res = snmpm:s(Id, Addr, Port, VAV), + reply(From, Res, Ref), + loop(S); + + + %% + %% -- (async) set-request -- + %% + + {{async_set, VAV}, From, Ref} -> + d("loop -> received async_set request"), + Res = [snmpm:async_set(Id, TargetName, VAV) || + TargetName <- snmpm:which_agents(Id)], + reply(From, Res, Ref), + loop(S); + + {{async_set, TargetName, VAV}, From, Ref} when is_list(TargetName) -> + d("loop -> received async_set request"), + Res = snmpm:async_set(Id, TargetName, VAV), + reply(From, Res, Ref), + loop(S); + + {{async_set, Addr, VAV}, From, Ref} -> + d("loop -> received async_set request"), + Res = snmpm:as(Id, Addr, VAV), + reply(From, Res, Ref), + loop(S); + + {{async_set, Addr, Port, VAV}, From, Ref} -> + d("loop -> received async_set request"), + Res = snmpm:as(Id, Addr, Port, VAV), + reply(From, Res, Ref), + loop(S); + + + %% + %% -- (sync) get-bulk-request -- + %% + + %% No agent specified, so send it to all of them + {{sync_get_bulk, NonRep, MaxRep, Oids}, From, Ref} -> + d("loop -> received sync_get_bulk request with" + "~n NonRep: ~w" + "~n MaxRep: ~w" + "~n Oids: ~p", [NonRep, MaxRep, Oids]), + Res = [snmpm:sync_get_bulk(Id, TargetName, NonRep, MaxRep, Oids) || + TargetName <- snmpm:which_agents(Id)], + reply(From, Res, Ref), + loop(S); + + {{sync_get_bulk, TargetName, NonRep, MaxRep, Oids}, From, Ref} when is_list(TargetName) -> + d("loop -> received sync_get_bulk request with" + "~n TargetName: ~p" + "~n NonRep: ~w" + "~n MaxRep: ~w" + "~n Oids: ~p", [TargetName, NonRep, MaxRep, Oids]), + Res = snmpm:sync_get_bulk(Id, TargetName, NonRep, MaxRep, Oids), + reply(From, Res, Ref), + loop(S); + + {{sync_get_bulk, Addr, NonRep, MaxRep, Oids}, From, Ref} -> + d("loop -> received sync_get_bulk request with" + "~n Addr: ~p" + "~n NonRep: ~w" + "~n MaxRep: ~w" + "~n Oids: ~p", [Addr, NonRep, MaxRep, Oids]), + Res = snmpm:gb(Id, Addr, NonRep, MaxRep, Oids), + reply(From, Res, Ref), + loop(S); + + {{sync_get_bulk, Addr, Port, NonRep, MaxRep, Oids}, From, Ref} -> + d("loop -> received sync_get_bulk request with" + "~n Addr: ~p" + "~n Port: ~w" + "~n NonRep: ~w" + "~n MaxRep: ~w" + "~n Oids: ~p", [Addr, Port, NonRep, MaxRep, Oids]), + Res = snmpm:gb(Id, Addr, Port, NonRep, MaxRep, Oids), + reply(From, Res, Ref), + loop(S); + + + %% + %% -- (async) get-bulk-request -- + %% + + %% No agent specified, so send it to all of them + {{async_get_bulk, NonRep, MaxRep, Oids}, From, Ref} -> + d("loop -> received async_get_bulk request with" + "~n NonRep: ~w" + "~n MaxRep: ~w" + "~n Oids: ~p", [NonRep, MaxRep, Oids]), + Res = [snmpm:async_get_bulk(Id, TargetName, NonRep, MaxRep, Oids) || + TargetName <- snmpm:which_agents(Id)], + reply(From, Res, Ref), + loop(S); + + {{async_get_bulk, TargetName, NonRep, MaxRep, Oids}, From, Ref} when is_list(TargetName) -> + d("loop -> received async_get_bulk request with" + "~n TargetName: ~p" + "~n NonRep: ~w" + "~n MaxRep: ~w" + "~n Oids: ~p", [TargetName, NonRep, MaxRep, Oids]), + Res = snmpm:async_get_bulk(Id, TargetName, NonRep, MaxRep, Oids), + reply(From, Res, Ref), + loop(S); + + {{async_get_bulk, Addr, NonRep, MaxRep, Oids}, From, Ref} -> + d("loop -> received async_get_bulk request with" + "~n Addr: ~p" + "~n NonRep: ~w" + "~n MaxRep: ~w" + "~n Oids: ~p", [Addr, NonRep, MaxRep, Oids]), + Res = snmpm:agb(Id, Addr, NonRep, MaxRep, Oids), + reply(From, Res, Ref), + loop(S); + + {{async_get_bulk, Addr, Port, NonRep, MaxRep, Oids}, From, Ref} -> + d("loop -> received async_get_bulk request with" + "~n Addr: ~p" + "~n Port: ~w" + "~n NonRep: ~w" + "~n MaxRep: ~w" + "~n Oids: ~p", [Addr, Port, NonRep, MaxRep, Oids]), + Res = snmpm:agb(Id, Addr, Port, NonRep, MaxRep, Oids), + reply(From, Res, Ref), + loop(S); + + + %% + %% -- logical name translation -- + %% + + {{name_to_oid, Name}, From, Ref} -> + d("loop -> received name_to_oid request for" + "~n Name: ~p", [Name]), + Res = snmpm:name_to_oid(Name), + reply(From, Res, Ref), + loop(S); + + {{oid_to_name, Oid}, From, Ref} -> + d("loop -> received oid_to_name request for" + "~n Oid: ~p", [Oid]), + Res = snmpm:oid_to_name(Oid), + reply(From, Res, Ref), + loop(S); + + {{purify_oid, Oid}, From, Ref} -> + d("loop -> received purify_oid request for" + "~n Oid: ~p", [Oid]), + Res = do_purify_oid(Oid), + reply(From, Res, Ref), + loop(S); + + + %% SNMP manager callback messages (from our callback API): + + {handle_error, _Pid, ReqId, Reason} -> + d("loop -> received error callback from manager for ~w:" + "~n ~p", [ReqId, Reason]), + Parent ! {async_event, ReqId, {error, Reason}}, + loop(S); + + {handle_agent, _Pid, Addr, Port, SnmpInfo} -> + d("loop -> received agent callback from manager for ~n ~p:~w", + [Addr, Port]), + Parent ! {async_event, {Addr, Port}, {agent, SnmpInfo}}, + loop(S); + + {handle_pdu, _Pid, _TargetName, ReqId, SnmpResponse} -> + d("loop -> received pdu callback from manager for ~w", [ReqId]), + Parent ! {async_event, ReqId, {pdu, SnmpResponse}}, + loop(S); + + %% For backwards compatibillity + {handle_pdu, _Pid, _Addr, _Port, ReqId, SnmpResponse} -> + d("loop -> received pdu callback from manager for ~w", [ReqId]), + Parent ! {async_event, ReqId, {pdu, SnmpResponse}}, + loop(S); + + {handle_trap, _Pid, TargetName, SnmpTrap} -> + d("loop -> received trap callback from manager for " + "~n ~p", + "~n ~p", + [TargetName, SnmpTrap]), + Parent ! {async_event, TargetName, {trap, SnmpTrap}}, + loop(S); + + %% For backwards compatibillity + {handle_trap, _Pid, Addr, Port, SnmpTrap} -> + d("loop -> received trap callback from manager for " + "~n ~p:~w", + "~n ~p", + [Addr, Port, SnmpTrap]), + Parent ! {async_event, {Addr, Port}, {trap, SnmpTrap}}, + loop(S); + + {handle_inform, Pid, TargetName, SnmpInform} -> + d("loop -> received inform callback from manager for " + "~n ~p", + "~n ~p", + [TargetName, SnmpInform]), + Parent ! {async_event, TargetName, {inform, Pid, SnmpInform}}, + loop(S); + + %% For backwards compatibillity + {handle_inform, Pid, Addr, Port, SnmpInform} -> + d("loop -> received inform callback from manager for " + "~n ~p:~w", + "~n ~p", + [Addr, Port, SnmpInform]), + Parent ! {async_event, {Addr, Port}, {inform, Pid, SnmpInform}}, + loop(S); + + {handle_report, _Pid, TargetName, SnmpReport} -> + d("loop -> received report callback from manager for " + "~n ~p", + "~n ~p", + [TargetName, SnmpReport]), + Parent ! {async_event, TargetName, {report, SnmpReport}}, + loop(S); + + %% For backwards compatibillity + {handle_report, _Pid, Addr, Port, SnmpReport} -> + d("loop -> received report callback from manager for " + "~n ~p:~w", + "~n ~p", + [Addr, Port, SnmpReport]), + Parent ! {async_event, {Addr, Port}, {report, SnmpReport}}, + loop(S); + + {'EXIT', Parent, Reason} -> + d("received exit signal from parent: ~n~p", [Reason]), + info("received exit signal from parent: ~n~p", [Reason]), + exit(Reason); + + Unknown -> + d("received unknown message: ~n~p", [Unknown]), + info("received unknown message: ~n~p", [Unknown]), + loop(S) + end. + + +%% ------------- + +do_purify_oid([A|T]) when is_atom(A) -> + case snmpm:name_to_oid(A) of + {ok, [Oid|_]} -> + verify_pure_oid(lists:flatten([Oid|T])); + {error, not_found} -> + {error, {not_found, A}}; + {error, _} = Error -> + Error + end; +do_purify_oid(L) when is_list(L) -> + verify_pure_oid(lists:flatten(L)); +do_purify_oid(X) -> + {error, {unpure_oid, X}}. + +verify_pure_oid([]) -> + []; +verify_pure_oid([H | T]) when is_integer(H) andalso (H >= 0) -> + [H | verify_pure_oid(T)]; +verify_pure_oid([H | _]) -> + throw({error, {not_pure_oid, H}}). + + +%% ------------- + +info(F, A) -> + error_logger:info_msg("TEST MGR USER " ++ F ++ "~n", A). + + +%% ------------- + +call(Req) -> + call(Req, 5000). + +call(Req, To) when is_integer(To) -> + Ref = make_ref(), + ?SERVER ! {Req, self(), Ref}, + receive + {Reply, Ref} -> + Reply + after To -> + {error, timeout} + end. + +reply(Pid, Reply, Ref) -> + Pid ! {Reply, Ref}. + +cast(Msg) -> + ?SERVER ! {Msg, self()}, + ok. + + +%%---------------------------------------------------------------------- +%% User callback functions: +%%---------------------------------------------------------------------- + +handle_error(ReqId, Reason, UserPid) -> + UserPid ! {handle_error, self(), ReqId, Reason}, + ignore. + + +handle_agent(Addr, Port, SnmpInfo, UserPid) -> + UserPid ! {handle_agent, self(), Addr, Port, SnmpInfo}, + ignore. + + +handle_pdu(TargetName, ReqId, SnmpResponse, UserPid) -> + UserPid ! {handle_pdu, self(), TargetName, ReqId, SnmpResponse}, + ignore. + +%% For backwards compatibillity +handle_pdu(Addr, Port, ReqId, SnmpResponse, UserPid) -> + UserPid ! {handle_pdu, self(), Addr, Port, ReqId, SnmpResponse}, + ignore. + + +handle_trap(TargetName, SnmpTrap, UserPid) -> + UserPid ! {handle_trap, self(), TargetName, SnmpTrap}, + ok. + +%% For backwards compatibillity +handle_trap(Addr, Port, SnmpTrap, UserPid) -> + UserPid ! {handle_trap, self(), Addr, Port, SnmpTrap}, + ok. + + +handle_inform(TargetName, SnmpInform, UserPid) -> + UserPid ! {handle_inform, self(), TargetName, SnmpInform}, + receive + {handle_inform_no_response, TargetName} -> + no_reply; + {handle_inform_response, TargetName} -> + ok + end. + +%% For backwards compatibillity +handle_inform(Addr, Port, SnmpInform, UserPid) -> + UserPid ! {handle_inform, self(), Addr, Port, SnmpInform}, + receive + {handle_inform_no_response, {Addr, Port}} -> + no_reply; + {handle_inform_response, {Addr, Port}} -> + ok + end. + + +handle_report(TargetName, SnmpReport, UserPid) -> + UserPid ! {handle_report, self(), TargetName, SnmpReport}, + ok. + +%% For backwards compatibillity +handle_report(Addr, Port, SnmpReport, UserPid) -> + UserPid ! {handle_report, self(), Addr, Port, SnmpReport}, + ok. + + +%%---------------------------------------------------------------------- +%% Debug +%%---------------------------------------------------------------------- + +d(F) -> + d(F, []). + +d(F, A) -> + d(get(debug), F, A). + +d(true, F, A) -> + io:format("~w:" ++ F ++ "~n", [?SERVER|A]); +d(_, _, _) -> + ok. diff --git a/lib/snmp/test/snmp_manager_user_old.erl b/lib/snmp/test/snmp_manager_user_old.erl new file mode 100755 index 0000000000..b53514d699 --- /dev/null +++ b/lib/snmp/test/snmp_manager_user_old.erl @@ -0,0 +1,264 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Utility functions for the (snmp manager) user test(s). +%%---------------------------------------------------------------------- + +-module(snmp_manager_user_old). + +-behaviour(snmpm_user_old). + + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + start/0, start/1, + stop/0, + register_agent/1, register_agent/2, register_agent/3, + unregister_agent/1, unregister_agent/2, + agent_info/3, + update_agent_info/4, + which_agents/0, which_users/0, + load_mib/1, unload_mib/1, + sync_get/2, sync_get/3, + async_get/2, async_get/3, + sync_get_next/2, sync_get_next/3, + async_get_next/2, async_get_next/3, + sync_set/2, sync_set/3, + async_set/2, async_set/3, + sync_get_bulk/4, sync_get_bulk/5, + async_get_bulk/4, async_get_bulk/5, + name_to_oid/1, oid_to_name/1, + purify_oid/1 + ]). + +-export([ + handle_error/3, + handle_agent/4, + handle_pdu/5, + handle_trap/4, + handle_inform/4, + handle_report/4 + ]). + + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- + +%% -define(SERVER, ?MODULE). +-define(USER_ID, ?MODULE). + +%% -record(state, {parent, id, reqs = []}). +%% -record(request, {from, ref, tmr, req_id, type}). + + +%%---------------------------------------------------------------------- +%% The user API +%%---------------------------------------------------------------------- + +start() -> + start([]). + +start(DefaultAgentConfig) when is_list(DefaultAgentConfig) -> + snmpm:register_user(?USER_ID, ?MODULE, self(), DefaultAgentConfig). + +stop() -> + snmpm:unregister_user(?USER_ID). + +register_agent(Addr) -> + snmpm:register_agent(?USER_ID, Addr). + +register_agent(Addr, PortOrConfig) -> + snmpm:register_agent(?USER_ID, Addr, PortOrConfig). + +register_agent(Addr, Port, Config) -> + snmpm:register_agent(?USER_ID, Addr, Port, Config). + +unregister_agent(Addr) -> + snmpm:unregister_agent(?USER_ID, Addr). + +unregister_agent(Addr, Port) -> + snmpm:unregister_agent(?USER_ID, Addr, Port). + +agent_info(Addr, Port, Item) -> + snmpm:agent_info(?USER_ID, Addr, Port, Item). + +update_agent_info(Addr, Port, Item, Val) -> + snmpm:update_agent_info(?USER_ID, Addr, Port, Item, Val). + +which_agents() -> + snmpm:which_agents(). + +which_users() -> + snmpm:which_users(). + +load_mib(Mib) -> + snmpm:load_mib(?USER_ID, Mib). + +unload_mib(Mib) -> + snmpm:unload_mib(?USER_ID, Mib). + + +%% -- + +sync_get(Addr, Oids) -> + snmpm:g(?USER_ID, Addr, Oids). + +sync_get(Addr, Port, Oids) -> + snmpm:g(?USER_ID, Addr, Port, Oids). + + +%% -- + +async_get(Addr, Oids) -> + snmpm:ag(?USER_ID, Addr, Oids). + +async_get(Addr, Port, Oids) -> + snmpm:ag(?USER_ID, Addr, Port, Oids). + + +%% -- + +sync_get_next(Addr, Oids) -> + snmpm:gn(?USER_ID, Addr, Oids). + +sync_get_next(Addr, Port, Oids) -> + snmpm:gn(?USER_ID, Addr, Port, Oids). + + +%% -- + +async_get_next(Addr, Oids) -> + snmpm:agn(?USER_ID, Addr, Oids). + +async_get_next(Addr, Port, Oids) -> + snmpm:agn(?USER_ID, Addr, Port, Oids). + + +%% -- + +sync_set(Addr, VAV) -> + snmpm:s(?USER_ID, Addr, VAV). + +sync_set(Addr, Port, VAV) -> + snmpm:s(?USER_ID, Addr, Port, VAV). + + +%% -- + +async_set(Addr, VAV) -> + snmpm:as(?USER_ID, Addr, VAV). + +async_set(Addr, Port, VAV) -> + snmpm:as(?USER_ID, Addr, Port, VAV). + + +%% -- + +sync_get_bulk(Addr, NonRep, MaxRep, Oids) -> + snmpm:gb(?USER_ID, Addr, NonRep, MaxRep, Oids). + +sync_get_bulk(Addr, Port, NonRep, MaxRep, Oids) -> + snmpm:gb(?USER_ID, Addr, Port, NonRep, MaxRep, Oids). + + +%% -- + +async_get_bulk(Addr, NonRep, MaxRep, Oids) -> + snmpm:agb(?USER_ID, Addr, NonRep, MaxRep, Oids). + +async_get_bulk(Addr, Port, NonRep, MaxRep, Oids) -> + snmpm:agb(?USER_ID, Addr, Port, NonRep, MaxRep, Oids). + + +%% -- + +name_to_oid(Name) -> + snmpm:name_to_oid(Name). + +oid_to_name(Oid) -> + snmpm:oid_to_name(Oid). + +purify_oid(Oid) -> + snmpm:purify_oid(Oid). + + +%%---------------------------------------------------------------------- +%% User callback functions: +%%---------------------------------------------------------------------- + +handle_error(ReqId, Reason, UserPid) -> + UserPid ! {handle_error, self(), ReqId, Reason}, + ignore. + + +handle_agent(Addr, Port, SnmpInfo, UserPid) -> + UserPid ! {handle_agent, self(), Addr, Port, SnmpInfo}, + ignore. + + +handle_pdu(Addr, Port, ReqId, SnmpResponse, UserPid) -> + UserPid ! {handle_pdu, self(), Addr, Port, ReqId, SnmpResponse}, + ignore. + + +handle_trap(Addr, Port, SnmpTrap, UserPid) -> + UserPid ! {handle_trap, self(), Addr, Port, SnmpTrap}, + ok. + + +handle_inform(Addr, Port, SnmpInform, UserPid) -> + UserPid ! {handle_inform, self(), Addr, Port, SnmpInform}, + receive + {handle_inform_no_response, {Addr, Port}} -> + no_reply; + {handle_inform_response, {Addr, Port}} -> + ok + end. + + +handle_report(Addr, Port, SnmpReport, UserPid) -> + UserPid ! {handle_report, self(), Addr, Port, SnmpReport}, + ok. + + +%%---------------------------------------------------------------------- +%% Debug +%%---------------------------------------------------------------------- + +%% d(F) -> +%% d(F, []). + +%% d(F, A) -> +%% d(get(debug), F, A). + +%% d(true, F, A) -> +%% io:format("~w:" ++ F ++ "~n", [?SERVER|A]); +%% d(_, _, _) -> +%% ok. diff --git a/lib/snmp/test/snmp_manager_user_test.erl b/lib/snmp/test/snmp_manager_user_test.erl new file mode 100644 index 0000000000..24ed3b0b73 --- /dev/null +++ b/lib/snmp/test/snmp_manager_user_test.erl @@ -0,0 +1,1244 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Various (snmp manager) user related tests +%%---------------------------------------------------------------------- +-module(snmp_manager_user_test). + + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +%% -compile(export_all). + +-export([ + all/1, + init_per_testcase/2, fin_per_testcase/2, + + register_user/1, + simple_register_and_unregister1/1, + simple_register_and_unregister2/1, + simple_register_and_unregister3/1, + register_and_crash1/1, + register_and_crash2/1, + register_and_crash3/1, + register_request_and_crash1/1, + register_request_and_crash2/1, + register_request_and_crash3/1, + simple_register_monitor_and_unregister1/1, + simple_register_monitor_and_unregister2/1, + simple_register_monitor_and_unregister3/1, + register_monitor_and_crash1/1, + register_monitor_and_crash2/1, + register_monitor_and_crash3/1, + register_monitor_and_crash4/1, + register_monitor_and_crash5/1, + register_monitor_request_and_crash1/1, + register_monitor_request_and_crash2/1, + register_monitor_request_and_crash3/1, + register_monitor_request_and_crash4/1, + + tickets/1, + otp7902/1 + + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + ]). + + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(Case, Config) when is_list(Config) -> + p("init_per_testcase -> Case: ~p", [Case]), + SnmpPrivDir = ?config(priv_dir, Config), + p("init_per_testcase -> SnmpPrivDir: ~p", [SnmpPrivDir]), + SuiteDir = atom_to_list(?MODULE), + SuiteTopDir = filename:join(SnmpPrivDir, SuiteDir), + case file:make_dir(SuiteTopDir) of + ok -> + ok; + {error, eexist} -> + ok; + {error, Reason} -> + ?FAIL({failed_creating, SuiteTopDir, Reason}) + end, + p("init_per_testcase -> SuiteTopDir: ~p", [SuiteTopDir]), + CaseDir = atom_to_list(Case), + ?line ok = + file:make_dir(CaseTopDir = filename:join(SuiteTopDir, CaseDir)), + p("init_per_testcase -> CaseTopDir: ~p", [CaseTopDir]), + ?line ok = + file:make_dir(MgrTopDir = filename:join(CaseTopDir, "manager/")), + ?line ok = + file:make_dir(MgrConfDir = filename:join(MgrTopDir, "conf/")), + ?line ok = + file:make_dir(MgrDbDir = filename:join(MgrTopDir, "db/")), + ?line ok = + file:make_dir(MgrLogDir = filename:join(MgrTopDir, "log/")), + [{suite_top_dir, SuiteTopDir}, + {case_top_dir, CaseTopDir}, + {manager_dir, MgrTopDir}, + {manager_conf_dir, MgrConfDir}, + {manager_db_dir, MgrDbDir}, + {manager_log_dir, MgrLogDir} | Config]. + + +fin_per_testcase(Case, Config) when is_list(Config) -> + p("fin_per_testcase -> Case: ~p", [Case]), +% MgrTopDir = ?config(manager_dir, Config), +% ?DEL_DIR(MgrTopDir), + Config. + + +%%====================================================================== +%% Test case definitions +%%====================================================================== + +all(suite) -> + [ + register_user, + tickets + ]. + +register_user(suite) -> + [ + simple_register_and_unregister1, + simple_register_and_unregister2, + simple_register_and_unregister3, + register_and_crash1, + register_and_crash2, + register_and_crash3, + register_request_and_crash1, + register_request_and_crash2, + register_request_and_crash3, + simple_register_monitor_and_unregister1, + simple_register_monitor_and_unregister2, + simple_register_monitor_and_unregister3, + register_monitor_and_crash1, + register_monitor_and_crash2, + register_monitor_and_crash3, + register_monitor_and_crash4, + register_monitor_and_crash5, + register_monitor_request_and_crash1, + register_monitor_request_and_crash2, + register_monitor_request_and_crash3, + register_monitor_request_and_crash4 + ]. + + +tickets(suite) -> + [ + otp7902 + ]. + + +%%====================================================================== +%% Test functions +%%====================================================================== + +simple_register_and_unregister1(suite) -> []; +simple_register_and_unregister1(doc) -> + "Start a user, register and unregister the user."; +simple_register_and_unregister1(Conf) when is_list(Conf) -> + put(tname,srar1), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id = make_ref(), + + ?line Pid = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user(Pid, Id), + + ?line [Id] = Users2 = which_users(), + p("Users2: ~p", [Users2]), + + ?line ok = unregister_user(Pid), + + ?line [] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + ?line stop_user(Pid), + + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +simple_register_and_unregister2(suite) -> []; +simple_register_and_unregister2(doc) -> + "Start a single user process, " + "register 2 users (per that process) and unregister the 2 users."; +simple_register_and_unregister2(Conf) when is_list(Conf) -> + put(tname,srar2), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id1 = make_ref(), + Id2 = make_ref(), + + ?line Pid = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user(Pid, Id1), + ?line ok = register_user(Pid, Id2), + + ?line Users2 = case which_users() of + [Id1, Id2] = U1 -> + U1; + [Id2, Id1] = U2 -> + U2; + Else -> + ?FAIL({invalid_users, Else}) + end, + p("Users2: ~p", [Users2]), + + + ?line ok = unregister_user(Pid, Id1), + ?line ok = unregister_user(Pid, Id2), + + ?line [] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + ?line stop_user(Pid), + + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +simple_register_and_unregister3(suite) -> []; +simple_register_and_unregister3(doc) -> + "Start 2 user processes, " + "register one users per process and unregister the 2 users."; +simple_register_and_unregister3(Conf) when is_list(Conf) -> + put(tname,srar2), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id1 = make_ref(), + Id2 = make_ref(), + + ?line Pid1 = start_user(), + ?line Pid2 = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user(Pid1, Id1), + ?line ok = register_user(Pid2, Id2), + + ?line Users2 = case which_users() of + [Id1, Id2] = U1 -> + U1; + [Id2, Id1] = U2 -> + U2; + Else -> + ?FAIL({invalid_users, Else}) + end, + p("Users2: ~p", [Users2]), + + + ?line ok = unregister_user(Pid1, Id1), + ?line ok = unregister_user(Pid2, Id2), + + ?line [] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + ?line stop_user(Pid1), + ?line stop_user(Pid2), + + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +register_and_crash1(suite) -> []; +register_and_crash1(doc) -> + "Start a user, register and crash user."; +register_and_crash1(Conf) when is_list(Conf) -> + put(tname,racau1), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ?line ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id = make_ref(), + + ?line Pid = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user(Pid, Id), + + ?line [Id] = Users2 = which_users(), + p("Users2: ~p", [Users2]), + + ?line ok = simulate_crash(Pid), + + ?line [Id] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + p("stop manager"), + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +register_and_crash2(suite) -> []; +register_and_crash2(doc) -> + "Start a single user process, " + "register 2 users (per that process) and crash the process."; +register_and_crash2(Conf) when is_list(Conf) -> + put(tname,racau2), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ?line ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id1 = make_ref(), + Id2 = make_ref(), + + ?line Pid = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user(Pid, Id1), + ?line ok = register_user(Pid, Id2), + + ?line Users2 = case which_users() of + [Id1, Id2] = U1 -> + U1; + [Id2, Id1] = U2 -> + U2; + Else1 -> + ?FAIL({invalid_users, Else1}) + end, + p("Users2: ~p", [Users2]), + + ?line ok = simulate_crash(Pid), + + ?line Users3 = case which_users() of + [Id1, Id2] = U3 -> + U3; + [Id2, Id1] = U4 -> + U4; + Else2 -> + ?FAIL({invalid_users, Else2}) + end, + p("Users3: ~p", [Users3]), + + p("stop manager"), + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +register_and_crash3(suite) -> []; +register_and_crash3(doc) -> + "Start 2 user processes, " + "register one user per process and " + "crash the first user process."; +register_and_crash3(Conf) when is_list(Conf) -> + %% put(tname,rac3), + %% p("start"), + %% process_flag(trap_exit, true), + ?SKIP(not_yet_implemented). + + +%% ------------------------------------------------------------------ + +register_request_and_crash1(suite) -> []; +register_request_and_crash1(doc) -> + "Start a single user process, " + "register user, send request and crash user."; +register_request_and_crash1(Conf) when is_list(Conf) -> + %% put(tname,rrac1), + %% p("start"), + %% process_flag(trap_exit, true), + ?SKIP(not_yet_implemented). + + +%% ------------------------------------------------------------------ + +register_request_and_crash2(suite) -> []; +register_request_and_crash2(doc) -> + "Start a single user process, " + "register 2 users (per that single user process), " + "send a request for each user and crash the single user process."; +register_request_and_crash2(Conf) when is_list(Conf) -> + %% put(tname,rrac2), + %% p("start"), + %% process_flag(trap_exit, true), + ?SKIP(not_yet_implemented). + + +%% ------------------------------------------------------------------ + +register_request_and_crash3(suite) -> []; +register_request_and_crash3(doc) -> + "Start 2 user processes, " + "register one user per process, " + "send a request for each user and crash the first user process."; +register_request_and_crash3(Conf) when is_list(Conf) -> + %% put(tname,rrac3), + %% p("start"), + %% process_flag(trap_exit, true), + ?SKIP(not_yet_implemented). + + +%% ------------------------------------------------------------------ + +simple_register_monitor_and_unregister1(suite) -> []; +simple_register_monitor_and_unregister1(doc) -> + "Start a user, register-link and unregister the user."; +simple_register_monitor_and_unregister1(Conf) when is_list(Conf) -> + put(tname,srlau1), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id = make_ref(), + + p("start user"), + ?line Pid = start_user(), + + p("get users (=0)"), + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + p("register monitored user"), + ?line ok = register_user_monitor(Pid, Id), + + p("get users (=1)"), + ?line [Id] = Users2 = which_users(), + p("Users2: ~p", [Users2]), + + p("unregister monitored user"), + ?line unregister_user(Pid), + + p("get users (=0)"), + ?line [] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + p("start user"), + ?line stop_user(Pid), + + p("stop manager"), + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +simple_register_monitor_and_unregister2(suite) -> []; +simple_register_monitor_and_unregister2(doc) -> + "Start a single user process, " + "register-link 2 users (per that process) and " + "unregister the 2 users."; +simple_register_monitor_and_unregister2(Conf) when is_list(Conf) -> + put(tname,srlau2), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id1 = make_ref(), + Id2 = make_ref(), + + ?line Pid = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user_monitor(Pid, Id1), + ?line ok = register_user_monitor(Pid, Id2), + + ?line Users2 = case which_users() of + [Id1, Id2] = U1 -> + U1; + [Id2, Id1] = U2 -> + U2; + Else -> + ?FAIL({invalid_users, Else}) + end, + p("Users2: ~p", [Users2]), + + ?line ok = unregister_user(Pid, Id1), + ?line ok = unregister_user(Pid, Id2), + + ?line [] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + ?line stop_user(Pid), + + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +simple_register_monitor_and_unregister3(suite) -> []; +simple_register_monitor_and_unregister3(doc) -> + "Start a single user process, " + "register one user and register-monitor one user " + "(per that process) and " + "unregister the 2 users."; +simple_register_monitor_and_unregister3(Conf) when is_list(Conf) -> + put(tname,srlau3), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id1 = make_ref(), + Id2 = make_ref(), + + ?line Pid = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user(Pid, Id1), + ?line ok = register_user_monitor(Pid, Id2), + + ?line Users2 = case which_users() of + [Id1, Id2] = U1 -> + U1; + [Id2, Id1] = U2 -> + U2; + Else -> + ?FAIL({invalid_users, Else}) + end, + p("Users2: ~p", [Users2]), + + ?line unregister_user(Pid), + + ?line [] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + ?line stop_user(Pid), + + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +register_monitor_and_crash1(suite) -> []; +register_monitor_and_crash1(doc) -> + "Start a user, register-monitor and crash the user."; +register_monitor_and_crash1(Conf) when is_list(Conf) -> + put(tname,rlac1), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ?line ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id = make_ref(), + + ?line Pid = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user_monitor(Pid, Id), + + ?line [Id] = Users2 = which_users(), + p("Users2: ~p", [Users2]), + + ?line ok = simulate_crash(Pid), + + ?SLEEP(1000), + + ?line [] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + p("stop manager"), + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +register_monitor_and_crash2(suite) -> []; +register_monitor_and_crash2(doc) -> + "Start a single user process, " + "register-monitor 2 users (per that process) " + "and crash the single user process."; +register_monitor_and_crash2(Conf) when is_list(Conf) -> + put(tname,rlac2), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ?line ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id1 = make_ref(), + Id2 = make_ref(), + + ?line Pid = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user_monitor(Pid, Id1), + ?line ok = register_user_monitor(Pid, Id2), + + ?line Users2 = case which_users() of + [Id1, Id2] = U1 -> + U1; + [Id2, Id1] = U2 -> + U2; + Else -> + ?FAIL({invalid_users, Else}) + end, + p("Users2: ~p", [Users2]), + + ?line ok = simulate_crash(Pid), + + ?SLEEP(1000), + + ?line [] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + p("stop manager"), + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +register_monitor_and_crash3(suite) -> []; +register_monitor_and_crash3(doc) -> + "Start a single user process, " + "register-monitor one user and register one user, " + "crash the single user process."; +register_monitor_and_crash3(Conf) when is_list(Conf) -> + put(tname,rlac3), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ?line ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id1 = make_ref(), + Id2 = make_ref(), + + ?line Pid = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user(Pid, Id1), + ?line ok = register_user_monitor(Pid, Id2), + + ?line Users2 = case which_users() of + [Id1, Id2] = U1 -> + U1; + [Id2, Id1] = U2 -> + U2; + Else -> + ?FAIL({invalid_users, Else}) + end, + p("Users2: ~p", [Users2]), + + ?line ok = simulate_crash(Pid), + + ?SLEEP(1000), + + ?line [Id1] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + p("stop manager"), + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +register_monitor_and_crash4(suite) -> []; +register_monitor_and_crash4(doc) -> + "Start 2 user processes, " + "register-monitor one user per process " + "and crash the first user process."; +register_monitor_and_crash4(Conf) when is_list(Conf) -> + put(tname,rlac4), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("start manager"), + ?line ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id1 = make_ref(), + Id2 = make_ref(), + + p("start user processes"), + ?line Pid1 = start_user(), + ?line Pid2 = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user_monitor(Pid1, Id1), + ?line ok = register_user_monitor(Pid2, Id2), + + ?line Users2 = case which_users() of + [Id1, Id2] = U1 -> + U1; + [Id2, Id1] = U2 -> + U2; + Else -> + ?FAIL({invalid_users, Else}) + end, + p("Users2: ~p", [Users2]), + + ?line ok = simulate_crash(Pid1), + + ?SLEEP(1000), + + ?line [Id2] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + ?line stop_user(Pid2), + + p("stop manager"), + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +register_monitor_and_crash5(suite) -> []; +register_monitor_and_crash5(doc) -> + "OTP-7961: " + "Start 2 user processes, " + "register-monitor a user for per process, " + "let each user register an agent " + "and crash the first user process."; +register_monitor_and_crash5(Conf) when is_list(Conf) -> + put(tname,rlac4), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("start manager"), + ?line ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + Id1 = gurka, %% make_ref(), + Id2 = tomat, %% make_ref(), + + p("start user processes"), + ?line Pid1 = start_user(), + ?line Pid2 = start_user(), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = register_user_monitor(Pid1, Id1), + ?line ok = register_user_monitor(Pid2, Id2), + + LocalHost = snmp_test_lib:localhost(), + + TargetName1 = "kalle1", + Address1 = LocalHost, + Port1 = 5001, + EngineId1 = "agentEngineId-1", + + TargetName2 = "kalle2", + Address2 = LocalHost, + Port2 = 5002, + EngineId2 = "agentEngineId-2", + + ?line ok = register_agent(Pid1, + Id1, TargetName1, [{address, Address1}, + {port, Port1}, + {engine_id, EngineId1}]), + ?line ok = register_agent(Pid2, + Id2, TargetName2, [{address, Address2}, + {port, Port2}, + {engine_id, EngineId2}]), + + ?line Users2 = case which_users() of + [Id1, Id2] = U1 -> + U1; + [Id2, Id1] = U2 -> + U2; + U3 -> + ?FAIL({invalid_users, U3}) + end, + p("Users2: ~p", [Users2]), + + p("verify all agent(s): expect 2"), + ?line Agents1 = case which_agents() of + [TargetName1, TargetName2] = A1 -> + A1; + [TargetName2, TargetName1] = A2 -> + A2; + A3 -> + ?FAIL({invalid_agents, A3}) + end, + p("Agents1: ~p", [Agents1]), + + ?line ok = simulate_crash(Pid1), + + p("wait some time"), + ?SLEEP(1000), + + ?line [Id2] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + ?line [TargetName2] = Agents2 = which_agents(), + p("Agents2: ~p", [Agents2]), + + ?line stop_user(Pid2), + + p("stop manager"), + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +register_monitor_request_and_crash1(suite) -> []; +register_monitor_request_and_crash1(doc) -> + "Start a single user process, " + "register-monitor one user, " + "send request and crash the user."; +register_monitor_request_and_crash1(Conf) when is_list(Conf) -> + %% put(tname,rlrac1), + %% p("start"), + %% process_flag(trap_exit, true), + ?SKIP(not_yet_implemented). + + +%% ------------------------------------------------------------------ + +register_monitor_request_and_crash2(suite) -> []; +register_monitor_request_and_crash2(doc) -> + "Start a single user process, " + "register-monitor 2 user (per that one process), " + "send a request for each user and crash the single user process."; +register_monitor_request_and_crash2(Conf) when is_list(Conf) -> + %% put(tname,rlrac2), + %% p("start"), + %% process_flag(trap_exit, true), + ?SKIP(not_yet_implemented). + + +%% ------------------------------------------------------------------ + +register_monitor_request_and_crash3(suite) -> []; +register_monitor_request_and_crash3(doc) -> + "Start a single user process, " + "register-monitor one user and register one user, " + "send a request for each user and crash the single user process."; +register_monitor_request_and_crash3(Conf) when is_list(Conf) -> + %% put(tname,rlrac3), + %% p("start"), + %% process_flag(trap_exit, true), + ?SKIP(not_yet_implemented). + + +%% ------------------------------------------------------------------ + +register_monitor_request_and_crash4(suite) -> []; +register_monitor_request_and_crash4(doc) -> + "Start 2 user processes, " + "register-monitor one user and register one user on the " + "first user process and do the same for the other user process, " + "then for each user, send a request and " + "crash the first user process."; +register_monitor_request_and_crash4(Conf) when is_list(Conf) -> + %% put(tname,rlrac4), + %% p("start"), + %% process_flag(trap_exit, true), + ?SKIP(not_yet_implemented). + + + +%% ------------------------------------------------------------------ + +otp7902(suite) -> []; +otp7902(doc) -> + "OTP-7902 - Start old user and make sure it wors."; +otp7902(Conf) when is_list(Conf) -> + put(tname, otp7902), + p("start"), + process_flag(trap_exit, true), + + ConfDir = ?config(manager_conf_dir, Conf), + DbDir = ?config(manager_db_dir, Conf), + + write_manager_conf(ConfDir), + + Opts = [{server, [{verbosity, trace}]}, + {net_if, [{verbosity, trace}]}, + {note_store, [{verbosity, trace}]}, + {config, [{verbosity, trace}, {dir, ConfDir}, {db_dir, DbDir}]}], + + p("try starting manager"), + ok = snmpm:start_link(Opts), + + ?SLEEP(1000), + + ?line [] = Users1 = which_users(), + p("Users1: ~p", [Users1]), + + ?line ok = snmp_manager_user_old:start(), + + ?line [_] = Users2 = which_users(), + p("Users2: ~p", [Users2]), + + ?line ok = snmp_manager_user_old:stop(), + + ?line [] = Users3 = which_users(), + p("Users3: ~p", [Users3]), + + ?line ok = snmpm:stop(), + + p("end"), + ok. + + +%% ------------------------------------------------------------------ + +start_user() -> + {ok, Pid} = snmp_manager_user_test_lib:start_link(), + Pid. + +stop_user(Pid) -> + snmp_manager_user_test_lib:stop(Pid). + +simulate_crash(Pid) -> + snmp_manager_user_test_lib:simulate_crash(Pid, simulate_crash), + receive + {'EXIT', Pid, simulate_crash} -> + ok; + {'EXIT', Pid, Whatever} -> + {ok, Whatever} + after 5000 -> + {error, timeout} + end. + +register_user(Pid, Id) -> + snmp_manager_user_test_lib:register(Pid, Id). + +register_user_monitor(Pid, Id) -> + snmp_manager_user_test_lib:register_monitor(Pid, Id). + +unregister_user(Pid) -> + case snmp_manager_user_test_lib:unregister(Pid) of + {ok, Res} -> + case [R || R <- Res, R =/= ok] of + [] -> + ok; + Errs -> + {error, Errs} + end; + Error -> + Error + end. + +unregister_user(Pid, Id) -> + snmp_manager_user_test_lib:unregister(Pid, Id). + + +register_agent(Pid, Id, TargetName, Config) -> + snmp_manager_user_test_lib:register_agent(Pid, Id, TargetName, Config). + + +%% ------ + +which_users() -> + snmpm:which_users(). + +which_agents() -> + snmpm:which_agents(). + + +%% ------ + + +write_manager_conf(Dir) -> + Port = "5000", + MMS = "484", + EngineID = "\"mgrEngine\"", + Str = lists:flatten( + io_lib:format("%% Minimum manager config file\n" + "{port, ~s}.\n" + "{max_message_size, ~s}.\n" + "{engine_id, ~s}.\n", + [Port, MMS, EngineID])), + write_manager_conf(Dir, Str). + +write_manager_conf(Dir, Str) -> + write_conf_file(Dir, "manager.conf", Str). + + +write_conf_file(Dir, File, Str) -> + ?line {ok, Fd} = file:open(filename:join(Dir, File), write), + ?line ok = io:format(Fd, "~s", [Str]), + file:close(Fd). + + +%% ------ + +p(F) -> + p(F, []). + +p(F, A) -> + p(get(tname), F, A). + +p(TName, F, A) -> + io:format("~w -> " ++ F ++ "~n", [TName|A]). + diff --git a/lib/snmp/test/snmp_manager_user_test_lib.erl b/lib/snmp/test/snmp_manager_user_test_lib.erl new file mode 100644 index 0000000000..a49fe93178 --- /dev/null +++ b/lib/snmp/test/snmp_manager_user_test_lib.erl @@ -0,0 +1,422 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Utility functions for the (snmp manager) user test(s). +%%---------------------------------------------------------------------- + +-module(snmp_manager_user_test_lib). + +-behaviour(snmpm_user). + + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + start_link/0, stop/1, + simulate_crash/2, + register/2, register/3, + register_monitor/2, register_monitor/3, + unregister/1, unregister/2, + register_agent/4 + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + user/1 + ]). + +-export([ + handle_error/3, + handle_agent/4, + handle_pdu/4, + handle_pdu/5, % For backwards compatibillity + handle_trap/3, + handle_trap/4, % For backwards compatibillity + handle_inform/3, + handle_inform/4, % For backwards compatibillity + handle_report/3, + handle_report/4 % For backwards compatibillity + ]). + + +-record(state, {parent, ids = []}). + + +%%---------------------------------------------------------------------- +%% The user simulation API +%%---------------------------------------------------------------------- + +start_link() -> + S = #state{parent = self()}, + proc_lib:start_link(?MODULE, user, [S]). + +stop(Pid) -> + cast(Pid, stop). + +simulate_crash(Pid, Reason) -> + call(Pid, {simulate_crash, Reason}). + +%% For backwards compatibillity +register(Pid, Id) -> + call(Pid, {register, Id}). + +register(Pid, Id, DefaultAgentConfig) -> + call(Pid, {register, Id, DefaultAgentConfig}). + +%% For backwards compatibillity +register_monitor(Pid, Id) -> + call(Pid, {register_monitor, Id}). + +register_monitor(Pid, Id, DefaultAgentConfig) -> + call(Pid, {register_monitor, Id, DefaultAgentConfig}). + +unregister(Pid) -> + call(Pid, unregister). + +unregister(Pid, Id) -> + call(Pid, {unregister, Id}). + +register_agent(Pid, Id, TargetName, AgentConfig) -> + call(Pid, {register_agent, Id, TargetName, AgentConfig}). + +user(#state{parent = Pid} = S) -> + proc_lib:init_ack(Pid, {ok, self()}), + user_loop(S). + +user_loop(#state{parent = Parent} = S) -> + receive + {stop, Parent} -> + exit(normal); + + {{simulate_crash, Reason}, Parent, Ref} -> + reply(Parent, ok, Ref), + exit(Reason); + + %% For backwards compatibillity + {{register, Id}, Parent, Ref} -> + IDs = S#state.ids, + case lists:member(Id, IDs) of + false -> + Res = snmpm:register_user(Id, ?MODULE, self()), + reply(Parent, Res, Ref), + user_loop(S#state{ids = [Id|IDs]}); + true -> + reply(Parent, {error, already_registered}, Ref), + user_loop(S) + end; + + {{register, Id, DefaultAgentConf}, Parent, Ref} -> + IDs = S#state.ids, + case lists:member(Id, IDs) of + false -> + Res = snmpm:register_user(Id, ?MODULE, self(), + DefaultAgentConf), + reply(Parent, Res, Ref), + user_loop(S#state{ids = [Id|IDs]}); + true -> + reply(Parent, {error, already_registered}, Ref), + user_loop(S) + end; + + %% For backwards compatibillity + {{register_monitor, Id}, Parent, Ref} -> + IDs = S#state.ids, + case lists:member(Id, IDs) of + false -> + Res = snmpm:register_user_monitor(Id, ?MODULE, self()), + reply(Parent, Res, Ref), + user_loop(S#state{ids = [Id|IDs]}); + true -> + reply(Parent, {error, already_registered}, Ref), + user_loop(S) + end; + + {{register_monitor, Id, DefaultAgentConf}, Parent, Ref} -> + IDs = S#state.ids, + case lists:member(Id, IDs) of + false -> + Res = snmpm:register_user_monitor(Id, ?MODULE, self(), + DefaultAgentConf), + reply(Parent, Res, Ref), + user_loop(S#state{ids = [Id|IDs]}); + true -> + reply(Parent, {error, already_registered}, Ref), + user_loop(S) + end; + + {unregister, Parent, Ref} -> + Res = [snmpm:unregister_user(Id) || Id <- S#state.ids], + reply(Parent, {ok, Res}, Ref), + user_loop(S); + + {{unregister, Id}, Parent, Ref} -> + IDs = S#state.ids, + IDs2 = + case lists:member(Id, IDs) of + true -> + Res = snmpm:unregister_user(Id), + reply(Parent, Res, Ref), + lists:delete(Id, IDs); + false -> + reply(Parent, {error, not_registered}, Ref), + IDs + end, + user_loop(S#state{ids = IDs2}); + + {{register_agent, Id, TargetName, Config}, Parent, Ref} -> + IDs = S#state.ids, + case lists:member(Id, IDs) of + true -> + Res = snmpm:register_agent(Id, TargetName, Config), + reply(Parent, Res, Ref), + user_loop(S); + false -> + reply(Parent, {error, {unknown_user, Id}}, Ref), + user_loop(S) + end; + + + + %% SNMP manager callback messages (from our callback API): + + {handle_error, Pid, ReqId, Reason} -> + do_handle_error(Pid, ReqId, Reason), + user_loop(S); + + {handle_agent, Pid, Addr, Port, SnmpInfo} -> + do_handle_agent(Pid, Addr, Port, SnmpInfo), + user_loop(S); + + {handle_pdu, Pid, TargetName, ReqId, SnmpResponse} -> + do_handle_pdu(Pid, TargetName, ReqId, SnmpResponse), + user_loop(S); + + {handle_pdu, Pid, Addr, Port, ReqId, SnmpResponse} -> + do_handle_pdu(Pid, Addr, Port, ReqId, SnmpResponse), + user_loop(S); + + {handle_trap, Pid, TargetName, SnmpTrap} -> + do_handle_trap(Pid, TargetName, SnmpTrap), + user_loop(S); + + {handle_trap, Pid, Addr, Port, SnmpTrap} -> + do_handle_trap(Pid, Addr, Port, SnmpTrap), + user_loop(S); + + {handle_inform, Pid, TargetName, SnmpInform} -> + do_handle_inform(Pid, TargetName, SnmpInform), + user_loop(S); + + {handle_inform, Pid, Addr, Port, SnmpInform} -> + do_handle_inform(Pid, Addr, Port, SnmpInform), + user_loop(S); + + {handle_report, Pid, TargetName, SnmpReport} -> + do_handle_report(Pid, TargetName, SnmpReport), + user_loop(S); + + {handle_report, Pid, Addr, Port, SnmpReport} -> + do_handle_report(Pid, Addr, Port, SnmpReport), + user_loop(S); + + Unknown -> + info("received unknown message: ~n~p", [Unknown]), + user_loop(S) + end. + + +%% ------------- + +do_handle_error(Pid, ReqId, Reason) -> + info("received error callback:" + "~n ReqId: ~p" + "~n Reason: ~p", [ReqId, Reason]), + Pid ! {ignore, self()}, + ok. + + +do_handle_agent(Pid, Addr, Port, SnmpInfo) -> + info("received agent callback:" + "~n Addr: ~p" + "~n Port: ~p" + "~n SnmpInfo: ~p", [Addr, Port, SnmpInfo]), + Pid ! {ignore, self()}, + ok. + + +do_handle_pdu(Pid, TargetName, ReqId, SnmpResponse) -> + info("received pdu callback:" + "~n TargetName: ~p" + "~n ReqId: ~p" + "~n SnmpResponse: ~p", [TargetName, ReqId, SnmpResponse]), + Pid ! {ignore, self()}, + ok. + +%% For backwards compatibillity +do_handle_pdu(Pid, Addr, Port, ReqId, SnmpResponse) -> + info("received pdu callback:" + "~n Addr: ~p" + "~n Port: ~p" + "~n ReqId: ~p" + "~n SnmpResponse: ~p", [Addr, Port, ReqId, SnmpResponse]), + Pid ! {ignore, self()}, + ok. + + +do_handle_trap(Pid, TargetName, SnmpTrap) -> + info("received trap callback:" + "~n TargetName: ~p" + "~n SnmpTrap: ~p", [TargetName, SnmpTrap]), + Pid ! {ignore, self()}, + ok. + +%% For backwards compatibillity +do_handle_trap(Pid, Addr, Port, SnmpTrap) -> + info("received trap callback:" + "~n Addr: ~p" + "~n Port: ~p" + "~n SnmpTrap: ~p", [Addr, Port, SnmpTrap]), + Pid ! {ignore, self()}, + ok. + + +do_handle_inform(Pid, TargetName, SnmpInform) -> + info("received inform callback:" + "~n TargetName: ~p" + "~n SnmpInform: ~p", [TargetName, SnmpInform]), + Pid ! {ignore, self()}, + ok. + +%% For backwards compatibillity +do_handle_inform(Pid, Addr, Port, SnmpInform) -> + info("received inform callback:" + "~n Addr: ~p" + "~n Port: ~p" + "~n SnmpInform: ~p", [Addr, Port, SnmpInform]), + Pid ! {ignore, self()}, + ok. + + +do_handle_report(Pid, TargetName, SnmpReport) -> + info("received report callback:" + "~n TargetName: ~p" + "~n SnmpReport: ~p", [TargetName, SnmpReport]), + Pid ! {ignore, self()}, + ok. + +%% For backwards compatibillity +do_handle_report(Pid, Addr, Port, SnmpReport) -> + info("received report callback:" + "~n Addr: ~p" + "~n Port: ~p" + "~n SnmpReport: ~p", [Addr, Port, SnmpReport]), + Pid ! {ignore, self()}, + ok. + + +info(F, A) -> + error_logger:info_msg("USER SIMULATOR " ++ F ++ "~n", A). + + +%% ------------- + +call(UserPid, Req) -> + call(UserPid, Req, 5000). + +call(UserPid, Req, To) -> + Ref = make_ref(), + UserPid ! {Req, self(), Ref}, + receive + {Reply, UserPid, Ref} -> + Reply + after To -> + {error, timeout} + end. + +reply(Pid, Reply, Ref) -> + Pid ! {Reply, self(), Ref}. + +cast(UserPid, Msg) -> + UserPid ! {Msg, self()}, + ok. + + +%%---------------------------------------------------------------------- +%% User callback functions: +%%---------------------------------------------------------------------- + +handle_error(ReqId, Reason, UserPid) -> + UserPid ! {handle_error, self(), ReqId, Reason}, + ignore. + + +handle_agent(Addr, Port, SnmpInfo, UserPid) -> + UserPid ! {handle_agent, self(), Addr, Port, SnmpInfo}, + ignore. + + +handle_pdu(TargetName, ReqId, SnmpResponse, UserPid) -> + UserPid ! {handle_pdu, self(), TargetName, ReqId, SnmpResponse}, + ignore. + +%% For backwards compatibillity +handle_pdu(Addr, Port, ReqId, SnmpResponse, UserPid) -> + UserPid ! {handle_pdu, self(), Addr, Port, ReqId, SnmpResponse}, + ignore. + + +handle_trap(TargetName, SnmpTrap, UserPid) -> + UserPid ! {handle_trap, self(), TargetName, SnmpTrap}, + ok. + +%% For backwards compatibillity +handle_trap(Addr, Port, SnmpTrap, UserPid) -> + UserPid ! {handle_trap, self(), Addr, Port, SnmpTrap}, + ok. + + +handle_inform(TargetName, SnmpInform, UserPid) -> + UserPid ! {handle_inform, self(), TargetName, SnmpInform}, + ok. + +%% For backwards compatibillity +handle_inform(Addr, Port, SnmpInform, UserPid) -> + UserPid ! {handle_inform, self(), Addr, Port, SnmpInform}, + ok. + + +handle_report(TargetName, SnmpReport, UserPid) -> + UserPid ! {handle_report, self(), TargetName, SnmpReport}, + ok. + +%% For backwards compatibillity +handle_report(Addr, Port, SnmpReport, UserPid) -> + UserPid ! {handle_report, self(), Addr, Port, SnmpReport}, + ok. diff --git a/lib/snmp/test/snmp_note_store_test.erl b/lib/snmp/test/snmp_note_store_test.erl new file mode 100644 index 0000000000..8686a47468 --- /dev/null +++ b/lib/snmp/test/snmp_note_store_test.erl @@ -0,0 +1,306 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: +%%---------------------------------------------------------------------- +-module(snmp_note_store_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + init_per_testcase/2, fin_per_testcase/2, + all/1, + start_and_stop/1, + notes/1, + info/1, + garbage_in/1 + ]). + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + system_start_time/0 + ]). + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +%%====================================================================== +%% Test case definitions +%%====================================================================== +all(suite) -> + [ + start_and_stop, + notes, + info, + garbage_in + + ]. + + +%%====================================================================== +%% Test functions +%%====================================================================== + + +%%====================================================================== + +start_and_stop(suite) -> + []; +start_and_stop(doc) -> + ["Simple start and stop."]; +start_and_stop(Config) when is_list(Config) -> + + Prio = normal, + Mod = ?MODULE, + Opts = [{verbosity, trace}], + {ok, Pid} = snmp_note_store:start_link(Prio, Mod, Opts), + snmp_note_store:stop(Pid), + + ok. + + +%%====================================================================== + +notes(suite) -> + []; +notes(doc) -> + ["Testing that it does what it is actually supposed to do, " + "namilly to handle notes. "]; +notes(Config) when is_list(Config) -> + + {ok, Handler, Pid} = note_store_handler_start(), + + io:format("sleep some before we begin the tests~n", []), + ?SLEEP(timer:seconds(1)), + + %% Default lifetime is infinity. A note with lifetime + %% infinity is permanent + io:format("create permanent note sune~n", []), + true = snmp_note_store:set_note(Pid, sune, 10), + 10 = snmp_note_store:get_note(Pid, sune), + 10 = snmp_note_store:get_note(Pid, sune), + + %% Lifetime is in 1/100 sec ticks, so 500 equals 5 seconds + io:format("create 5 sec note kalle~n", []), + true = snmp_note_store:set_note(Pid, 500, kalle, hobbe), + io:format("wait 1 sec~n", []), + ?SLEEP(timer:seconds(1)), + io:format("get note kalle~n", []), + hobbe = snmp_note_store:get_note(Pid, kalle), + io:format("wait 5 sec~n", []), + ?SLEEP(timer:seconds(5)), + io:format("get note kalle again (now it should not exist)~n", []), + undefined = snmp_note_store:get_note(Pid, kalle), + + io:format("create 5 sec note kalle~n", []), + true = snmp_note_store:set_note(Pid, 500, kalle, hobbe), + io:format("wait 6 sec (to allow timer to clean up note)~n", []), + ?SLEEP(timer:seconds(6)), + io:format("get note kalle - should not exist~n", []), + undefined = snmp_note_store:get_note(Pid, kalle), + + io:format("read the permanent note sune again~n", []), + 10 = snmp_note_store:get_note(Pid, sune), + + note_store_handler_stop(Handler), + + ok. + + +%%====================================================================== + +info(suite) -> + []; +info(doc) -> + ["Testing that we can retreive process info."]; +info(Config) when is_list(Config) -> + + Prio = normal, + Mod = ?MODULE, + Opts = [{verbosity, trace}], + {ok, Pid} = snmp_note_store:start_link(Prio, Mod, Opts), + + %% Get the info: + Info = snmp_note_store:info(Pid), + io:format("Info: ~p~n", [Info]), + + %% Verify content + io:format("get process memory~n", []), + {value, {process_memory, ProcMem}} = + lists:keysearch(process_memory, 1, Info), + io:format("get notes process memory~n", []), + {value, {notes, NotesProcMem}} = + lists:keysearch(notes, 1, ProcMem), + io:format("verify notes process memory~n", []), + if + is_integer(NotesProcMem) andalso (NotesProcMem > 0) -> + ok; + true -> + throw({error, {bad_notes_proc_memery, NotesProcMem}}) + end, + io:format("get timer process memory~n", []), + {value, {timer, TmrProcMem}} = + lists:keysearch(timer, 1, ProcMem), + io:format("verify timer process memory~n", []), + if + is_integer(TmrProcMem) andalso (TmrProcMem > 0) -> + ok; + true -> + throw({error, {bad_timer_proc_memery, TmrProcMem}}) + end, + io:format("get db memory~n", []), + {value, {db_memory, DbMem}} = + lists:keysearch(db_memory, 1, Info), + io:format("get notes db memory~n", []), + {value, {notes, NotesDbMem}} = + lists:keysearch(notes, 1, DbMem), + io:format("verify notes db memory~n", []), + if + is_integer(NotesDbMem) andalso (NotesDbMem > 0) -> + ok; + true -> + throw({error, {bad_notes_db_memery, NotesDbMem}}) + end, + + + snmp_note_store:stop(Pid), + + ok. + + +%%====================================================================== + +garbage_in(suite) -> + []; +garbage_in(doc) -> + ["Test that the process handles garbage sent to it."]; +garbage_in(Config) when is_list(Config) -> + + io:format("start note_store server~n", []), + Prio = normal, + Mod = ?MODULE, + Opts = [{verbosity, trace}], + {ok, Pid} = snmp_note_store:start_link(Prio, Mod, Opts), + + io:format("issue bad request~n", []), + {error, _} = gen_server:call(Pid, bad_request), + + io:format("cast bad message~n", []), + gen_server:cast(Pid, bad_message), + + io:format("bang bad info~n", []), + Pid ! bad_info, + + io:format("verify note_Store server still alive and kicking~n", []), + Info = snmp_note_store:info(Pid), + if + is_list(Info) andalso (length(Info) > 0) -> + ok; + true -> + throw({error, {bad_info, Info}}) + end, + + io:format("stop note_store server~n", []), + snmp_note_store:stop(Pid), + + io:format("done~n", []), + ok. + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +system_start_time() -> + note_store_handler ! {system_start_time, self()}, + receive + {system_start_time, SysStartTime} -> + SysStartTime + end. + +note_store_handler_start() -> + Self = self(), + Fun = fun() -> note_store_handler(Self) end, + HandlerPid = spawn_link(Fun), + receive + {started, HandlerPid, NSPid} -> + {ok, HandlerPid, NSPid} + after 5000 -> + exit(HandlerPid, kill), + {error, timeout} + end. + +note_store_handler_stop(Pid) -> + Pid ! {stop, self()}, + receive + {stopped, Pid} -> + ok + after 5000 -> + exit(Pid, kill), + {error, timeout} + end. + +note_store_handler(Parent) -> + erlang:register(note_store_handler, self()), + put(system_start_time, snmp_misc:now(cs)), + Prio = normal, + Mod = ?MODULE, + Opts = [{verbosity, trace}], + {ok, Pid} = snmp_note_store:start_link(Prio, Mod, Opts), + Parent ! {started, self(), Pid}, + note_store_handler_loop(Parent, Pid). + +note_store_handler_loop(Parent, NSPid) -> + receive + {stop, Parent} -> + snmp_note_store:stop(NSPid), + Parent ! {stopped, self()}, + exit(normal); + {system_start_time, Pid} -> + StartTime = get(system_start_time), + Pid ! {system_start_time, StartTime}, + note_store_handler_loop(Parent, NSPid) + end. + diff --git a/lib/snmp/test/snmp_pdus_test.erl b/lib/snmp/test/snmp_pdus_test.erl new file mode 100644 index 0000000000..d5add50f52 --- /dev/null +++ b/lib/snmp/test/snmp_pdus_test.erl @@ -0,0 +1,127 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: +%%---------------------------------------------------------------------- +-module(snmp_pdus_test). + +%%---------------------------------------------------------------------- +%% Include files +%%---------------------------------------------------------------------- +-include("test_server.hrl"). +-include("snmp_test_lib.hrl"). +-include_lib("snmp/include/snmp_types.hrl"). + + +%%---------------------------------------------------------------------- +%% External exports +%%---------------------------------------------------------------------- +-export([ + all/1, + tickets/1, + otp7575/1, + init_per_testcase/2, fin_per_testcase/2 + ]). + + +%%---------------------------------------------------------------------- +%% Internal exports +%%---------------------------------------------------------------------- +-export([ + ]). + + +%%---------------------------------------------------------------------- +%% Macros +%%---------------------------------------------------------------------- + +%%---------------------------------------------------------------------- +%% Records +%%---------------------------------------------------------------------- + +%%====================================================================== +%% External functions +%%====================================================================== + +init_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +fin_per_testcase(_Case, Config) when is_list(Config) -> + Config. + +%%====================================================================== +%% Test case definitions +%%====================================================================== +all(suite) -> + [ + tickets + ]. + +tickets(suite) -> + [ + otp7575 + ]. + + + +%%====================================================================== +%% Test functions +%%====================================================================== + +otp7575(suite) -> []; +otp7575(doc) -> ["OTP-7575"]; +otp7575(Config) when is_list(Config) -> + io:format("attempt to decode message with valid version~n", []), + MsgWithOkVersion = <<48,39,2,1,0,4,6,112,117,98,108,105,99,160,26,2,2,1,49,2,1,0,2,1,0,48,14,48,12,6,8,43,6,1,2,1,1,5,0,5,0>>, + case (catch dec_message(MsgWithOkVersion)) of + Msg when is_record(Msg, message) -> + ok; + Unexpected1 -> + exit({unexpected_decode_result, 1, Unexpected1}) + end, + + io:format("attempt to decode message with bad version~n", []), + MsgWithBadVersion = <<48,48,2,10,1,1,1,1,1,1,1,1,1,1,4,6,112,117,98,108,105,99,160,26,2,2,1,49,2,1,0,2,1,0,48,14,48,12,6,8,43,6,1,2,1,1,5,0,5,0>>, + case (catch dec_message(MsgWithBadVersion)) of + {'EXIT', {bad_version, BadVersion}} when is_integer(BadVersion) -> + ok; + Unexpected2 -> + exit({unexpected_decode_result, 2, Unexpected2}) + end, + + io:format("attempt to decode message with very bad version~n", []), + MsgWithVeryBadVersion = <<48,49,2,11,1,1,1,1,1,1,1,1,1,1,1,4,6,112,117,98,108,105,99,160,26,2,2,1,49,2,1,0,2,1,0,48,14,48,12,6,8,43,6,1,2,1,1,5,0,5,0>>, + case (catch dec_message(MsgWithVeryBadVersion)) of + {'EXIT', {bad_version, {VersionSize, MaxVersionSize}}} when (VersionSize > MaxVersionSize) -> + ok; + Unexpected3 -> + exit({unexpected_decode_result, 3, Unexpected3}) + end, + io:format("done~n", []), + ok. + + +%%====================================================================== +%% Internal functions +%%====================================================================== + +dec_message(B) when is_binary(B) -> + L = binary_to_list(B), + snmp_pdus:dec_message(L). diff --git a/lib/snmp/test/snmp_test_data/ERICSSON-TOP-MIB.mib b/lib/snmp/test/snmp_test_data/ERICSSON-TOP-MIB.mib new file mode 100644 index 0000000000..8b5f594426 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/ERICSSON-TOP-MIB.mib @@ -0,0 +1,36 @@ +-- ERICSSON-TOP-MIB: Top-level MIB for Ericsson AB's +-- 193 branch of the enterprise MIB tree. +-- +-- ERICSSON-TOP-MIB.mib,v 1.1 2002/06/12 13:14:57 epkpart Exp +-- +-- ERICSSON-TOP-MIB.mib,v +-- Revision 1.1 2002/06/12 13:14:57 epkpart +-- Initial revision +-- +-- +-- Copyright (c) 2002 by Ericsson AB +-- All rights reserved. +-- + +ERICSSON-TOP-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, enterprises + FROM SNMPv2-SMI; + +ericsson MODULE-IDENTITY + LAST-UPDATED + "200205280000Z" + ORGANIZATION + "Ericsson AB " + CONTACT-INFO + "David Partain <[email protected]> + or + whoever is currently responsible for the Ericsson + enterprise MIB tree branch (enterprises.193)." + DESCRIPTION + "This very small module is made available so that + developers within the Ericsson community can import the + 'ericsson' name into their own MIB modules." + ::= { enterprises 193 } +END diff --git a/lib/snmp/test/snmp_test_data/EX1-MIB.mib b/lib/snmp/test/snmp_test_data/EX1-MIB.mib new file mode 100644 index 0000000000..5d9979d0b4 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/EX1-MIB.mib @@ -0,0 +1,90 @@ + EX1-MIB DEFINITIONS ::= BEGIN + + IMPORTS + experimental FROM RFC1155-SMI + RowStatus FROM STANDARD-MIB + DisplayString FROM RFC1213-MIB + OBJECT-TYPE FROM RFC-1212 + ; + + example1 OBJECT IDENTIFIER ::= { experimental 7 } + + + myName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "My own name" + ::= { example1 1 } + + friendsTable OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of friends." + ::= { example1 4 } + + friendsEntry OBJECT-TYPE + SYNTAX FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + INDEX { fIndex } + ::= { friendsTable 1 } + + FriendsEntry ::= + SEQUENCE { + fIndex + INTEGER, + fName + DisplayString, + fAddress + DisplayString, + fStatus + RowStatus } + + fIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "number of friend" + ::= { friendsEntry 1 } + + fName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Name of friend" + ::= { friendsEntry 2 } + + fAddress OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Address of friend" + ::= { friendsEntry 3 } + + fStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry 4 } + + + fTrap TRAP-TYPE + ENTERPRISE example1 + VARIABLES { myName, fIndex } + DESCRIPTION + "This trap is sent something happens to + the friend specified by fIndex." + ::= 1 + + END diff --git a/lib/snmp/test/snmp_test_data/Klas1-v2.mib b/lib/snmp/test/snmp_test_data/Klas1-v2.mib new file mode 100644 index 0000000000..ebbd157841 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Klas1-v2.mib @@ -0,0 +1,128 @@ + Klas1-V2 DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2, enterprises, IpAddress, + Integer32 + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp, RowStatus, TruthValue, + TEXTUAL-CONVENTION + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF; + +klas1v2 MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "" + CONTACT-INFO + "" + DESCRIPTION + "v2 variant of Klas1. Used for compatibility testing." + ::= { snmpModules 1 } + + klas1 OBJECT IDENTIFIER ::= { mib-2 7 } + + + fname OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "A textual description of the entity. This value + printable ASCII characters." + ::= { klas1 1 } + + friendsTable OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of klas friends." + ::= { klas1 4 } + + friendsEntry OBJECT-TYPE + SYNTAX FriendsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "nope" + INDEX { fIndex } + ::= { friendsTable 1 } + + FriendsEntry ::= + SEQUENCE { + fIndex + Integer32, + fName + DisplayString, + fStatus + RowStatus } + + fIndex OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "number of friend" + ::= { friendsEntry 1 } + + fName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Name of friend" + ::= { friendsEntry 2 } + + fStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry 3 } + + kompissTable OBJECT-TYPE + SYNTAX SEQUENCE OF KompissEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of klas kompiss." + ::= { klas1 5 } + + kompissEntry OBJECT-TYPE + SYNTAX KompissEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "nope" + INDEX { fIndex } + ::= { kompissTable 1 } + + KompissEntry ::= + SEQUENCE { + kName + DisplayString, + kStatus + RowStatus } + + kName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Name of kompis" + ::= { kompissEntry 1 } + + kStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row." + ::= { kompissEntry 2 } + + + + END + diff --git a/lib/snmp/test/snmp_test_data/Klas1.mib b/lib/snmp/test/snmp_test_data/Klas1.mib new file mode 100644 index 0000000000..b07dc4d241 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Klas1.mib @@ -0,0 +1,116 @@ + Klas1 DEFINITIONS ::= BEGIN + + IMPORTS + mib-2 FROM RFC1213-MIB + RowStatus FROM STANDARD-MIB + OBJECT-TYPE + FROM RFC-1212; + + klas1 OBJECT IDENTIFIER ::= { mib-2 7 } + + DisplayString ::= + OCTET STRING + + fname OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + printable ASCII characters." + ::= { klas1 1 } + + friendsTable OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas friends." + ::= { klas1 4 } + + friendsEntry OBJECT-TYPE + SYNTAX FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex } + ::= { friendsTable 1 } + + FriendsEntry ::= + SEQUENCE { + fIndex + INTEGER, + fName + DisplayString, + fStatus + RowStatus } + + fIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "number of friend" + ::= { friendsEntry 1 } + + fName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Name of friend" + ::= { friendsEntry 2 } + + fStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry 3 } + + kompissTable OBJECT-TYPE + SYNTAX SEQUENCE OF KompissEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas kompiss." + ::= { klas1 5 } + + kompissEntry OBJECT-TYPE + SYNTAX KompissEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex } + ::= { kompissTable 1 } + + KompissEntry ::= + SEQUENCE { + kName + DisplayString, + kStatus + RowStatus } + + kName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Name of kompis" + ::= { kompissEntry 1 } + + kStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { kompissEntry 2 } + + + + END + diff --git a/lib/snmp/test/snmp_test_data/Klas2.funcs b/lib/snmp/test/snmp_test_data/Klas2.funcs new file mode 100644 index 0000000000..5dca2ef651 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Klas2.funcs @@ -0,0 +1,3 @@ +{friendsTable2, {snmp_generic, table_func, [{friendsTable2, mnesia}]}}. +{kompissTable2, {snmp_generic, table_func, [{kompissTable2, mnesia}]}}. +{fname2, {snmp_generic, variable_func, [{fname2, mnesia}]}}. diff --git a/lib/snmp/test/snmp_test_data/Klas2.mib b/lib/snmp/test/snmp_test_data/Klas2.mib new file mode 100644 index 0000000000..38ebf4ece7 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Klas2.mib @@ -0,0 +1,128 @@ + Klas2 DEFINITIONS ::= BEGIN + +-- This MIB is used for testing the Mnesia implementation + + IMPORTS + mib-2 FROM RFC1213-MIB + RowStatus FROM STANDARD-MIB + OBJECT-TYPE + FROM RFC-1212; + + klas2 OBJECT IDENTIFIER ::= { mib-2 9 } + + DisplayString ::= + OCTET STRING + + fname2 OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + printable ASCII characters." + ::= { klas2 1 } + + fint OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "write a neg. number to me if you dare..." + ::= { klas2 2 } + + + friendsTable2 OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry2 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas friends." + ::= { klas2 4 } + + friendsEntry2 OBJECT-TYPE + SYNTAX FriendsEntry2 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex2 } + ::= { friendsTable2 1 } + + FriendsEntry2 ::= + SEQUENCE { + fIndex2 + INTEGER, + fName2 + DisplayString, + fStatus2 + RowStatus } + + fIndex2 OBJECT-TYPE + SYNTAX INTEGER + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "number of friend" + ::= { friendsEntry2 1 } + + fName2 OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Name of friend" + ::= { friendsEntry2 2 } + + fStatus2 OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry2 3 } + + kompissTable2 OBJECT-TYPE + SYNTAX SEQUENCE OF KompissEntry2 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas kompiss." + ::= { klas2 5 } + + kompissEntry2 OBJECT-TYPE + SYNTAX KompissEntry2 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex2 } + ::= { kompissTable2 1 } + + KompissEntry2 ::= + SEQUENCE { + kName2 + DisplayString, + kStatus2 + RowStatus } + + kName2 OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Name of kompis" + DEFVAL { '4a4a4a'H } + ::= { kompissEntry2 1 } + + kStatus2 OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { kompissEntry2 2 } + + + + END + diff --git a/lib/snmp/test/snmp_test_data/Klas3.funcs b/lib/snmp/test/snmp_test_data/Klas3.funcs new file mode 100644 index 0000000000..8ed45cc4ca --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Klas3.funcs @@ -0,0 +1,2 @@ +{fname3, {klas3, fname, []}}. +{fname4, {klas3, fname4, []}}. diff --git a/lib/snmp/test/snmp_test_data/Klas3.mib b/lib/snmp/test/snmp_test_data/Klas3.mib new file mode 100644 index 0000000000..fc74e69ddd --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Klas3.mib @@ -0,0 +1,40 @@ + Klas3 DEFINITIONS ::= BEGIN + +-- This MIB is used for testing the undo phase + + IMPORTS + mib-2 FROM RFC1213-MIB + RowStatus FROM STANDARD-MIB + OBJECT-TYPE + FROM RFC-1212; + + klas3 OBJECT IDENTIFIER ::= { mib-2 8 } + + DisplayString ::= + OCTET STRING + + fname3 OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + printable ASCII characters." + ::= { klas3 1 } + + fname4 OBJECT-TYPE + SYNTAX INTEGER { + none(1), + snmpTrap(3) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + printable ASCII characters." + ::= { klas3 2 } + + + + END + diff --git a/lib/snmp/test/snmp_test_data/Klas4.funcs b/lib/snmp/test/snmp_test_data/Klas4.funcs new file mode 100644 index 0000000000..ef36f225a6 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Klas4.funcs @@ -0,0 +1,3 @@ +{friendsTable3, {klas3, ftab, []}}. +{friendsTable4, {klas3, ftab2, []}}. + diff --git a/lib/snmp/test/snmp_test_data/Klas4.mib b/lib/snmp/test/snmp_test_data/Klas4.mib new file mode 100644 index 0000000000..36b82d7d08 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Klas4.mib @@ -0,0 +1,156 @@ + Klas4 DEFINITIONS ::= BEGIN + +-- This MIB is used for testing the undo phase + + IMPORTS + mib-2 FROM RFC1213-MIB + RowStatus FROM STANDARD-MIB + OBJECT-TYPE + FROM RFC-1212 + klas3 FROM Klas3; + + DisplayString ::= + OCTET STRING + + friendsTable3 OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry3 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas friends." + ::= { klas3 4 } + + friendsEntry3 OBJECT-TYPE + SYNTAX FriendsEntry3 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex3 } + ::= { friendsTable3 1 } + + FriendsEntry3 ::= + SEQUENCE { + fIndex3 + INTEGER, + fStatus3 + RowStatus } + + fIndex3 OBJECT-TYPE + SYNTAX INTEGER + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "number of friend" + ::= { friendsEntry3 1 } + + fStatus3 OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry3 2 } + + friendsTable4 OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry4 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas friends." + ::= { klas3 5 } + + friendsEntry4 OBJECT-TYPE + SYNTAX FriendsEntry4 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex4 } + ::= { friendsTable4 1 } + + FriendsEntry4 ::= + SEQUENCE { + fIndex4 + INTEGER, + fName4 + INTEGER, + fStatus4 + RowStatus } + + fIndex4 OBJECT-TYPE + SYNTAX INTEGER + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "number of friend" + ::= { friendsEntry4 1 } + + fName4 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "name of friend" + ::= { friendsEntry4 2 } + + fStatus4 OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry4 3 } + + friendsTable5 OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry5 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas friends." + ::= { klas3 6 } + + friendsEntry5 OBJECT-TYPE + SYNTAX FriendsEntry5 + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex5 } + ::= { friendsTable5 1 } + + FriendsEntry5 ::= + SEQUENCE { + fIndex5 + INTEGER, + fName5 + INTEGER, + fStatus5 + RowStatus } + + fIndex5 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "number of friend" + ::= { friendsEntry5 1 } + + fName5 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "name of friend" + ::= { friendsEntry5 2 } + + fStatus5 OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry5 3 } + + END + diff --git a/lib/snmp/test/snmp_test_data/OLD-SNMPEA-MIB-v2.mib b/lib/snmp/test/snmp_test_data/OLD-SNMPEA-MIB-v2.mib new file mode 100644 index 0000000000..4f8ce94792 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/OLD-SNMPEA-MIB-v2.mib @@ -0,0 +1,480 @@ +OLD-SNMPEA-MIB-v2 DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2, enterprises, IpAddress, + Integer32 + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp, RowStatus, TruthValue, + TEXTUAL-CONVENTION + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF; + +internalMIBv2 MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "" + CONTACT-INFO + "" + DESCRIPTION + "v2 variant of INTERNAL-MIB. Used for compatibility testing." + ::= { snmpModules 1 } + + +ericsson OBJECT IDENTIFIER ::= {enterprises 193} +otp OBJECT IDENTIFIER ::= {ericsson 19} + +otpApplications + OBJECT IDENTIFIER ::= {otp 3} +otpSnmpeaMIB OBJECT IDENTIFIER ::= { otpApplications 3 } +otpSnmpeaMIBObjects + OBJECT IDENTIFIER ::= { otpSnmpeaMIB 2 } + +snmpeaAdm OBJECT IDENTIFIER ::= { otpSnmpeaMIBObjects 1} +community OBJECT IDENTIFIER ::= { snmpeaAdm 1 } +trap OBJECT IDENTIFIER ::= { snmpeaAdm 2 } +view OBJECT IDENTIFIER ::= { snmpeaAdm 3 } + + -- Datatype + +StorageType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Describes the memory realization of a conceptual row. A + row which is volatile(2) is lost upon reboot. A row which + is either nonVolatile(3), permanent(4) or readOnly(5), is + backed up by stable storage. A row which is permanent(4) + can be changed but not deleted. A row which is readOnly(5) + cannot be changed nor deleted. + + If the value of an object with this syntax is either + permanent(4) or readOnly(5), it cannot be modified. + Conversely, if the value is either other(1), volatile(2) or + nonVolatile(3), it cannot be modified to be permanent(4) or + readOnly(5). + + Every usage of this textual convention is required to + specify the columnar objects which a permanent(4) row must + at a minimum allow to be writable." + SYNTAX INTEGER { + other(1), -- eh? + volatile(2), -- e.g., in RAM + nonVolatile(3), -- e.g., in NVRAM + permanent(4) -- e.g., partially in ROM + } + + -- Managed Objects + + intCommunityTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntCommunityEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table defines access for the different + communities. + + When a request comes from a certain ip address, + referring to a community string, the mib view + and access corresponding to these are looked up + in this table. Then the operation is validatated against + the access, and all requested objects validated against + the mib view." + ::= { community 1} + + intCommunityEntry OBJECT-TYPE + SYNTAX IntCommunityEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { intCommunityDestination, intCommunityString } + ::= { intCommunityTable 1 } + + IntCommunityEntry ::= + SEQUENCE { + intCommunityDestination IpAddress, + intCommunityString DisplayString, + intCommunityViewIndex Integer32, + intCommunityAccess INTEGER, + intCommunityStatus RowStatus + } + + intCommunityDestination OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The ip address of a management station. The special + ip address {0.0.0.0} is a wildcard, meaning all possible + ip addresses. In this way, access can be granted to all + ip addressed for some communities." + ::= { intCommunityEntry 1 } + + intCommunityString OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The community string, defining the community." + ::= { intCommunityEntry 2 } + + intCommunityViewIndex OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Identifies a mib view. Index into the + intViewTable." + ::= { intCommunityEntry 3 } + + intCommunityAccess OBJECT-TYPE + SYNTAX INTEGER { read(1), readWrite(2) } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Defines which operations the manager can perform + on the objects in the mib view." + ::= { intCommunityEntry 4 } + + intCommunityStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row in the + intCommunityTable." + ::= { intCommunityEntry 5 } + + intAgentIpAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The IP address of this agent." + ::= { community 2 } + + intAgentUDPPort OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The UDP port the agent listens to." + DEFVAL { 161 } + ::= { community 3 } + + intAgentMaxPacketSize OBJECT-TYPE + SYNTAX INTEGER (484..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum packet size in bytes this agent will send to a + manager." + ::= { community 4 } + + + intAddressTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntAddressEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table holds UDP related information on each known + management station." + ::= { community 5 } + + + intAddressEntry OBJECT-TYPE + SYNTAX IntAddressEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { intAddressDestination } + ::= { intAddressTable 1 } + + IntAddressEntry ::= + SEQUENCE { + intAddressDestination IpAddress, + intAddressUDPPort INTEGER, + intAddressMaxPacketSize INTEGER (484..65535), + intAddressStatus RowStatus + } + + intAddressDestination OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The ip address of the management station." + ::= { intAddressEntry 1 } + + intAddressUDPPort OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The UDP port to which traps will be sent to + this destination." + DEFVAL { 162 } + ::= { intAddressEntry 2 } + + intAddressMaxPacketSize OBJECT-TYPE + SYNTAX INTEGER (484..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum packet size in bytes for Messages + sent to this destination. The max size of a packet + sent to this destination will be the minumim of + this variable and agentMaxPacketSize.0." + ::= { intAddressEntry 3 } + + intAddressStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row in the + intAddressTable." + ::= { intAddressEntry 4 } + + intTrapDestTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntTrapDestEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The intTrapDestTable defines to which destination all traps + for a specific community should be sent." + ::= { trap 1 } + + intTrapDestEntry OBJECT-TYPE + SYNTAX IntTrapDestEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + INDEX { intTrapDestCommunityString, intTrapDestDestination } + ::= { intTrapDestTable 1 } + + IntTrapDestEntry ::= + SEQUENCE { + intTrapDestCommunityString DisplayString, + intTrapDestDestination IpAddress, + intTrapDestStatus RowStatus + } + + intTrapDestCommunityString OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { intTrapDestEntry 1 } + + intTrapDestDestination OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { intTrapDestEntry 2 } + + intTrapDestStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row in the + intTrapDestTable." + ::= { intTrapDestEntry 3 } + + intViewTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntViewEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Locally held information about the MIB views + known to this agent. + + Each MIB view is defined by two + collections of view subtrees: the included view + subtrees, and the excluded view subtrees. Every + such subtree, both included and excluded, is + defined in this table. + + To determine if a particular object instance is in + a particular MIB view, compare the object + instance's OBJECT IDENTIFIER with each of the MIB + view's entries in this table. If none match, then + the object instance is not in the MIB view. If + one or more match, then the object instance is + included in, or excluded from, the MIB view + according to the value of viewType in the entry + whose value of viewSubtree has the most sub- + identifiers. If multiple entries match and have + the same number of sub-identifiers, then the + lexicographically greatest instance of viewType + determines the inclusion or exclusion. + + An object instance's OBJECT IDENTIFIER X matches + an entry in this table when the number of sub- + identifiers in X is at least as many as in the + value of viewSubtree for the entry, and each sub- + identifier in the value of viewSubtree matches its + corresponding sub-identifier in X. Two sub- + identifiers match either if the corresponding bit + of viewMask is zero (the 'wild card' value), or if + they are equal. + + Due to this 'wild card' capability, we introduce + the term, a 'family' of view subtrees, to refer to + the set of subtrees defined by a particular + combination of values of viewSubtree and viewMask. + In the case where no 'wild card' is defined in + viewMask, the family of view subtrees reduces to a + single view subtree." + ::= { view 1 } + + intViewEntry OBJECT-TYPE + SYNTAX IntViewEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Information on a particular family of view + subtrees included in or excluded from a particular + MIB view. + + Implementations must not restrict the number of + families of view subtrees for a given MIB view, + except as dictated by resource constraints on the + overall number of entries in the viewTable." + INDEX { intViewIndex, intViewSubtree } + ::= { intViewTable 1 } + + IntViewEntry ::= + SEQUENCE { + intViewIndex INTEGER, + intViewSubtree OBJECT IDENTIFIER, + intViewMask OCTET STRING, + intViewType INTEGER, + intViewStorageType StorageType, + intViewStatus RowStatus + } + + + intViewIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A unique value for each MIB view. The value for + each MIB view must remain constant at least from + one re-initialization of the entity's network + management system to the next re-initialization." + ::= { intViewEntry 1 } + + intViewSubtree OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A MIB subtree." + ::= { intViewEntry 2 } + + intViewMask OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..16)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The bit mask which, in combination with the + corresponding instance of viewSubtree, defines a + family of view subtrees. + + Each bit of this bit mask corresponds to a sub- + identifier of viewSubtree, with the most + significant bit of the i-th octet of this octet + string value (extended if necessary, see below) + corresponding to the (8*i - 7)-th sub-identifier, + and the least significant bit of the i-th octet of + this octet string corresponding to the (8*i)-th + sub-identifier, where i is in the range 1 through + 16. + + Each bit of this bit mask specifies whether or not + the corresponding sub-identifiers must match when + determining if an OBJECT IDENTIFIER is in this + family of view subtrees; a '1' indicates that an + exact match must occur; a '0' indicates 'wild + card', i.e., any sub-identifier value matches. + + + Thus, the OBJECT IDENTIFIER X of an object + instance is contained in a family of view subtrees + if the following criteria are met: + + for each sub-identifier of the value of + viewSubtree, either: + + the i-th bit of viewMask is 0, or + + the i-th sub-identifier of X is equal to + the i-th sub-identifier of the value of + viewSubtree. + + If the value of this bit mask is M bits long and + there are more than M sub-identifiers in the + corresponding instance of viewSubtree, then the + bit mask is extended with 1's to be the required + length. + + Note that when the value of this object is the + zero-length string, this extension rule results in + a mask of all-1's being used (i.e., no 'wild + card'), and the family of view subtrees is the one + view subtree uniquely identified by the + corresponding instance of viewSubtree." + DEFVAL { ''H } + ::= { intViewEntry 3 } + + + intViewType OBJECT-TYPE + SYNTAX INTEGER { + included(1), + excluded(2) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of a particular family of view + subtrees within the particular + MIB view. The value 'included(1)' indicates that + the corresponding instances of viewSubtree and + viewMask define a family of view subtrees included + in the MIB view. The value 'excluded(2)' + indicates that the corresponding instances of + viewSubtree and viewMask define a family of view + subtrees excluded from the MIB view." + DEFVAL { included } + ::= { intViewEntry 4 } + + intViewStorageType OBJECT-TYPE + SYNTAX StorageType + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The storage type for this conceptual row in the + intViewTable." + DEFVAL { nonVolatile } + ::= { intViewEntry 5 } + + intViewStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row in the + intViewTable." + ::= { intViewEntry 6 } + + + +END diff --git a/lib/snmp/test/snmp_test_data/OLD-SNMPEA-MIB.mib b/lib/snmp/test/snmp_test_data/OLD-SNMPEA-MIB.mib new file mode 100644 index 0000000000..dd90d0ab50 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/OLD-SNMPEA-MIB.mib @@ -0,0 +1,487 @@ +OLD-SNMPEA-MIB DEFINITIONS ::= BEGIN + + IMPORTS + enterprises, IpAddress + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212 + DisplayString + FROM RFC1213-MIB + RowStatus + FROM STANDARD-MIB + ; + +-- MODULE-IDENTITY +-- LAST-UPDATED "9709220900Z" +-- ORGANIZATION "ETX/DN/S" +-- CONTACT-INFO +-- " Martin Bj�rklund +-- +-- Postal: ERICSSON SOFTWARE TECHNOLOGY AB +-- ERLANG SYSTEMS +-- Box 1214 +-- S-164 28 KISTA, SWEDEN +-- +-- Tel: +46 8 719 20 89 +-- E-mail: [email protected]" +-- DESCRIPTION +-- "This MIB module defines MIB objects for the SNMPEA +-- component in OTP." +-- REVISION "9709220900Z" +-- DESCRIPTION +-- "The initial version of this MIB module. It is the old +-- INTERNAL-MIB renamed." + +ericsson OBJECT IDENTIFIER ::= {enterprises 193} +otp OBJECT IDENTIFIER ::= {ericsson 19} + +otpApplications + OBJECT IDENTIFIER ::= {otp 3} +otpSnmpeaMIB OBJECT IDENTIFIER ::= { otpApplications 3 } +otpSnmpeaMIBObjects + OBJECT IDENTIFIER ::= { otpSnmpeaMIB 2 } + +snmpeaAdm OBJECT IDENTIFIER ::= { otpSnmpeaMIBObjects 1} +community OBJECT IDENTIFIER ::= { snmpeaAdm 1 } +trap OBJECT IDENTIFIER ::= { snmpeaAdm 2 } +view OBJECT IDENTIFIER ::= { snmpeaAdm 3 } + + +-- Textual Conventions + +StorageType ::= + INTEGER { + other(1), -- eh? + volatile(2), -- e.g., in RAM + nonVolatile(3), -- e.g., in NVRAM + permanent(4) -- e.g., in ROM + } + +-- The Administration Group +-- +-- This group consists of objects to configure the access for +-- managers to the MIB tree. +-- +-- These objects were previously defined in INTERNAL-MIB + + +intCommunityTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntCommunityEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "This table defines access for the different + communities. + + When a request comes from a certain ip address, + referring to a community string, the mib view + and access corresponding to these are looked up + in this table. Then the operation is validatated against + the access, and all requested objects validated against + the mib view." + ::= { community 1} + +intCommunityEntry OBJECT-TYPE + SYNTAX IntCommunityEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + INDEX { intCommunityDestination, intCommunityString } + ::= { intCommunityTable 1 } + +IntCommunityEntry ::= + SEQUENCE { + intCommunityDestination IpAddress, + intCommunityString DisplayString, + intCommunityViewIndex INTEGER, + intCommunityAccess INTEGER, + intCommunityStatus RowStatus + } + +intCommunityDestination OBJECT-TYPE + SYNTAX IpAddress + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The ip address of a management station. The special + ip address {0.0.0.0} is a wildcard, meaning all possible + ip addresses. In this way, access can be granted to all + ip addressed for some communities." + ::= { intCommunityEntry 1 } + +intCommunityString OBJECT-TYPE + SYNTAX DisplayString + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The community string, defining the community." + ::= { intCommunityEntry 2 } + +intCommunityViewIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Identifies a mib view. Index into the + intViewTable." + ::= { intCommunityEntry 3 } + +intCommunityAccess OBJECT-TYPE + SYNTAX INTEGER { read(1), readWrite(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Defines which operations the manager can perform + on the objects in the mib view." + ::= { intCommunityEntry 4 } + +intCommunityStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row in the + intCommunityTable." + ::= { intCommunityEntry 5 } + +intAgentIpAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The IP address of this agent." + ::= { community 2 } + +intAgentUDPPort OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The UDP port the agent listens to." + ::= { community 3 } + +intAgentMaxPacketSize OBJECT-TYPE + SYNTAX INTEGER (484..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum packet size in bytes this agent will send to a + manager." + ::= { community 4 } + + +intAddressTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntAddressEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "This table holds UDP related information on each known + management station." + ::= { community 5 } + + +intAddressEntry OBJECT-TYPE + SYNTAX IntAddressEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + INDEX { intAddressDestination } + ::= { intAddressTable 1 } + +IntAddressEntry ::= + SEQUENCE { + intAddressDestination IpAddress, + intAddressUDPPort INTEGER, + intAddressMaxPacketSize INTEGER (484..65535), + intAddressStatus RowStatus + } + +intAddressDestination OBJECT-TYPE + SYNTAX IpAddress + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The ip address of the management station." + ::= { intAddressEntry 1 } + +intAddressUDPPort OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The UDP port to which traps will be sent to + this destination." + DEFVAL { 162 } + ::= { intAddressEntry 2 } + +intAddressMaxPacketSize OBJECT-TYPE + SYNTAX INTEGER (484..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The maximum packet size in bytes for Messages + sent to this destination. The max size of a packet + sent to this destination will be the minumim of + this variable and agentMaxPacketSize.0." + ::= { intAddressEntry 3 } + +intAddressStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row in the + intAddressTable." + ::= { intAddressEntry 4 } + +intTrapDestTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntTrapDestEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The intTrapDestTable defines to which destination all traps + for a specific community should be sent." + ::= { trap 1 } + +intTrapDestEntry OBJECT-TYPE + SYNTAX IntTrapDestEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + INDEX { intTrapDestCommunityString, intTrapDestDestination } + ::= { intTrapDestTable 1 } + +IntTrapDestEntry ::= + SEQUENCE { + intTrapDestCommunityString DisplayString, + intTrapDestDestination IpAddress, + intTrapDestStatus RowStatus, + intTrapDestSnmpVersion INTEGER + } + +intTrapDestCommunityString OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + ::= { intTrapDestEntry 1 } + +intTrapDestDestination OBJECT-TYPE + SYNTAX IpAddress + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + ::= { intTrapDestEntry 2 } + +intTrapDestStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row in the + intTrapDestTable." + ::= { intTrapDestEntry 3 } + +intTrapDestSnmpVersion OBJECT-TYPE + SYNTAX INTEGER { v1(1), v2(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The SNMP version of the manager. If it is v1, + SNMPv1Traps are sent. If it is v2, SNMPv2Traps are sent" + ::= { intTrapDestEntry 4 } + +intViewTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntViewEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Locally held information about the MIB views + known to this agent. + + Each MIB view is defined by two + collections of view subtrees: the included view + subtrees, and the excluded view subtrees. Every + such subtree, both included and excluded, is + defined in this table. + + To determine if a particular object instance is in + a particular MIB view, compare the object + instance's OBJECT IDENTIFIER with each of the MIB + view's entries in this table. If none match, then + the object instance is not in the MIB view. If + one or more match, then the object instance is + included in, or excluded from, the MIB view + according to the value of viewType in the entry + whose value of viewSubtree has the most sub- + identifiers. If multiple entries match and have + the same number of sub-identifiers, then the + lexicographically greatest instance of viewType + determines the inclusion or exclusion. + + An object instance's OBJECT IDENTIFIER X matches + an entry in this table when the number of sub- + identifiers in X is at least as many as in the + value of viewSubtree for the entry, and each sub- + identifier in the value of viewSubtree matches its + corresponding sub-identifier in X. Two sub- + identifiers match either if the corresponding bit + of viewMask is zero (the 'wild card' value), or if + they are equal. + + Due to this 'wild card' capability, we introduce + the term, a 'family' of view subtrees, to refer to + the set of subtrees defined by a particular + combination of values of viewSubtree and viewMask. + In the case where no 'wild card' is defined in + viewMask, the family of view subtrees reduces to a + single view subtree." + ::= { view 1 } + +intViewEntry OBJECT-TYPE + SYNTAX IntViewEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information on a particular family of view + subtrees included in or excluded from a particular + MIB view. + + Implementations must not restrict the number of + families of view subtrees for a given MIB view, + except as dictated by resource constraints on the + overall number of entries in the viewTable." + INDEX { intViewIndex, intViewSubtree } + ::= { intViewTable 1 } + +IntViewEntry ::= + SEQUENCE { + intViewIndex INTEGER, + intViewSubtree OBJECT IDENTIFIER, + intViewMask OCTET STRING, + intViewType INTEGER, + intViewStorageType StorageType, + intViewStatus RowStatus + } + + +intViewIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A unique value for each MIB view. The value for + each MIB view must remain constant at least from + one re-initialization of the entity's network + management system to the next re-initialization." + ::= { intViewEntry 1 } + +intViewSubtree OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A MIB subtree." + ::= { intViewEntry 2 } + +intViewMask OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..16)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The bit mask which, in combination with the + corresponding instance of viewSubtree, defines a + family of view subtrees. + + Each bit of this bit mask corresponds to a sub- + identifier of viewSubtree, with the most + significant bit of the i-th octet of this octet + string value (extended if necessary, see below) + corresponding to the (8*i - 7)-th sub-identifier, + and the least significant bit of the i-th octet of + this octet string corresponding to the (8*i)-th + sub-identifier, where i is in the range 1 through + 16. + + Each bit of this bit mask specifies whether or not + the corresponding sub-identifiers must match when + determining if an OBJECT IDENTIFIER is in this + family of view subtrees; a '1' indicates that an + exact match must occur; a '0' indicates 'wild + card', i.e., any sub-identifier value matches. + + + Thus, the OBJECT IDENTIFIER X of an object + instance is contained in a family of view subtrees + if the following criteria are met: + + for each sub-identifier of the value of + viewSubtree, either: + + the i-th bit of viewMask is 0, or + + the i-th sub-identifier of X is equal to + the i-th sub-identifier of the value of + viewSubtree. + + If the value of this bit mask is M bits long and + there are more than M sub-identifiers in the + corresponding instance of viewSubtree, then the + bit mask is extended with 1's to be the required + length. + + Note that when the value of this object is the + zero-length string, this extension rule results in + a mask of all-1's being used (i.e., no 'wild + card'), and the family of view subtrees is the one + view subtree uniquely identified by the + corresponding instance of viewSubtree." + DEFVAL { ''H } + ::= { intViewEntry 3 } + + +intViewType OBJECT-TYPE + SYNTAX INTEGER { + included(1), + excluded(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of a particular family of view + subtrees within the particular + MIB view. The value 'included(1)' indicates that + the corresponding instances of viewSubtree and + viewMask define a family of view subtrees included + in the MIB view. The value 'excluded(2)' + indicates that the corresponding instances of + viewSubtree and viewMask define a family of view + subtrees excluded from the MIB view." + DEFVAL { included } + ::= { intViewEntry 4 } + +intViewStorageType OBJECT-TYPE + SYNTAX StorageType + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The storage type for this conceptual row in the + intViewTable." + DEFVAL { nonVolatile } + ::= { intViewEntry 5 } + +intViewStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row in the + intViewTable." + ::= { intViewEntry 6 } + +END diff --git a/lib/snmp/test/snmp_test_data/PROXY.mib b/lib/snmp/test/snmp_test_data/PROXY.mib new file mode 100644 index 0000000000..5eb31429e7 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/PROXY.mib @@ -0,0 +1,60 @@ +PROXY DEFINITIONS ::= BEGIN + + IMPORTS + Counter, TimeTicks, IpAddress, enterprises + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212 + mgmt, NetworkAddress, IpAddress, Counter, Gauge, + TimeTicks + FROM RFC1155-SMI + DisplayString, mib-2 + FROM RFC1213-MIB + sysContact + FROM STANDARD-MIB + OBJECT-TYPE + FROM RFC-1212 + intViewSubtree + FROM OTP-SNMPEA-MIB; + + +ericsson OBJECT IDENTIFIER ::= {enterprises 193} +proxy OBJECT IDENTIFIER ::= { ericsson 12 } + + + proxyTest OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + should include the full name and version + identification of the system's hardware type, + software operating-system, and networking + software. It is mandatory that this only contain + printable ASCII characters." + ::= { proxy 1 } + + + proxyTrap TRAP-TYPE + ENTERPRISE ericsson + VARIABLES { sysContact, proxyTest } + DESCRIPTION + "A linkUp trap signifies that the sending + protocol entity recognizes that one of the + communication links represented in the agent's + configuration has come up." + ::= 3 + + proxyTrap2 TRAP-TYPE + ENTERPRISE ericsson + VARIABLES { sysContact, proxyTest, intViewSubtree } + DESCRIPTION + "A linkUp trap signifies that the sending + protocol entity recognizes that one of the + communication links represented in the agent's + configuration has come up." + ::= 5 + + +END diff --git a/lib/snmp/test/snmp_test_data/RFC1213-MIB.mib b/lib/snmp/test/snmp_test_data/RFC1213-MIB.mib new file mode 100644 index 0000000000..0421e64d62 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/RFC1213-MIB.mib @@ -0,0 +1,2888 @@ + RFC1213-MIB DEFINITIONS ::= BEGIN + + IMPORTS + mgmt, NetworkAddress, IpAddress, Counter, Gauge, + TimeTicks + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212; + + -- This MIB module uses the extended OBJECT-TYPE macro as + -- defined in [14]; + + + -- MIB-II (same prefix as MIB-I) + + mib-2 OBJECT IDENTIFIER ::= { mgmt 1 } + + -- textual conventions + + DisplayString ::= + OCTET STRING + -- This data type is used to model textual information taken + -- from the NVT ASCII character set. By convention, objects + -- with this syntax are declared as having + + + + -- + -- SIZE (0..255) + + PhysAddress ::= + OCTET STRING + -- This data type is used to model media addresses. For many + -- types of media, this will be in a binary representation. + -- For example, an ethernet address would be represented as + -- a string of 6 octets. + + + -- groups in MIB-II + + system OBJECT IDENTIFIER ::= { mib-2 1 } + + interfaces OBJECT IDENTIFIER ::= { mib-2 2 } + + at OBJECT IDENTIFIER ::= { mib-2 3 } + + ip OBJECT IDENTIFIER ::= { mib-2 4 } + + icmp OBJECT IDENTIFIER ::= { mib-2 5 } + + tcp OBJECT IDENTIFIER ::= { mib-2 6 } + + udp OBJECT IDENTIFIER ::= { mib-2 7 } + + egp OBJECT IDENTIFIER ::= { mib-2 8 } + + -- historical (some say hysterical) + -- cmot OBJECT IDENTIFIER ::= { mib-2 9 } + + transmission OBJECT IDENTIFIER ::= { mib-2 10 } + + snmp OBJECT IDENTIFIER ::= { mib-2 11 } + + + -- the System group + + -- Implementation of the System group is mandatory for all + -- systems. If an agent is not configured to have a value + -- for any of these variables, a string of length 0 is + -- returned. + + sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "A textual description of the entity. This value + should include the full name and version + identification of the system's hardware type, + software operating-system, and networking + software. It is mandatory that this only contain + printable ASCII characters." + ::= { system 1 } + + sysObjectID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The vendor's authoritative identification of the + network management subsystem contained in the + entity. This value is allocated within the SMI + enterprises subtree (1.3.6.1.4.1) and provides an + easy and unambiguous means for determining `what + kind of box' is being managed. For example, if + vendor `Flintstones, Inc.' was assigned the + subtree 1.3.6.1.4.1.4242, it could assign the + identifier 1.3.6.1.4.1.4242.1.1 to its `Fred + Router'." + ::= { system 2 } + + sysUpTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The time (in hundredths of a second) since the + network management portion of the system was last + re-initialized." + ::= { system 3 } + + sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The textual identification of the contact person + for this managed node, together with information + on how to contact this person." + ::= { system 4 } + + sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + + + + + + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An administratively-assigned name for this + managed node. By convention, this is the node's + fully-qualified domain name." + ::= { system 5 } + + sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The physical location of this node (e.g., + `telephone closet, 3rd floor')." + ::= { system 6 } + + sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A value which indicates the set of services that + this entity primarily offers. + + The value is a sum. This sum initially takes the + value zero, Then, for each layer, L, in the range + 1 through 7, that this node performs transactions + for, 2 raised to (L - 1) is added to the sum. For + example, a node which performs primarily routing + functions would have a value of 4 (2^(3-1)). In + contrast, a node which is a host offering + application services would have a value of 72 + (2^(4-1) + 2^(7-1)). Note that in the context of + the Internet suite of protocols, values should be + calculated accordingly: + + layer functionality + 1 physical (e.g., repeaters) + 2 datalink/subnetwork (e.g., bridges) + 3 internet (e.g., IP gateways) + 4 end-to-end (e.g., IP hosts) + 7 applications (e.g., mail relays) + + For systems including OSI protocols, layers 5 and + 6 may also be counted." + ::= { system 7 } + + + + + + + -- the Interfaces group + + -- Implementation of the Interfaces group is mandatory for + -- all systems. + + ifNumber OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of network interfaces (regardless of + their current state) present on this system." + ::= { interfaces 1 } + + + -- the Interfaces table + + -- The Interfaces table contains information on the entity's + -- interfaces. Each interface is thought of as being + -- attached to a `subnetwork'. Note that this term should + -- not be confused with `subnet' which refers to an + -- addressing partitioning scheme used in the Internet suite + -- of protocols. + + ifTable OBJECT-TYPE + SYNTAX SEQUENCE OF IfEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of interface entries. The number of + entries is given by the value of ifNumber." + ::= { interfaces 2 } + + ifEntry OBJECT-TYPE + SYNTAX IfEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "An interface entry containing objects at the + subnetwork layer and below for a particular + interface." + INDEX { ifIndex } + ::= { ifTable 1 } + + IfEntry ::= + SEQUENCE { + ifIndex + INTEGER, + ifDescr + DisplayString, + ifType + INTEGER, + ifMtu + INTEGER, + ifSpeed + Gauge, + ifPhysAddress + PhysAddress, + ifAdminStatus + INTEGER, + ifOperStatus + INTEGER, + ifLastChange + TimeTicks, + ifInOctets + Counter, + ifInUcastPkts + Counter, + ifInNUcastPkts + Counter, + ifInDiscards + Counter, + ifInErrors + Counter, + ifInUnknownProtos + Counter, + ifOutOctets + Counter, + ifOutUcastPkts + Counter, + ifOutNUcastPkts + Counter, + ifOutDiscards + Counter, + ifOutErrors + Counter, + ifOutQLen + Gauge, + ifSpecific + OBJECT IDENTIFIER + } + + ifIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "A unique value for each interface. Its value + ranges between 1 and the value of ifNumber. The + value for each interface must remain constant at + least from one re-initialization of the entity's + network management system to the next re- + initialization." + ::= { ifEntry 1 } + + ifDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A textual string containing information about the + interface. This string should include the name of + the manufacturer, the product name and the version + of the hardware interface." + ::= { ifEntry 2 } + + ifType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + regular1822(2), + hdh1822(3), + ddn-x25(4), + rfc877-x25(5), + ethernet-csmacd(6), + iso88023-csmacd(7), + iso88024-tokenBus(8), + iso88025-tokenRing(9), + iso88026-man(10), + starLan(11), + proteon-10Mbit(12), + proteon-80Mbit(13), + hyperchannel(14), + fddi(15), + lapb(16), + sdlc(17), + ds1(18), -- T-1 + e1(19), -- european equiv. of T-1 + basicISDN(20), + primaryISDN(21), -- proprietary serial + propPointToPointSerial(22), + ppp(23), + softwareLoopback(24), + eon(25), -- CLNP over IP [11] + ethernet-3Mbit(26), + + + + + + nsip(27), -- XNS over IP + slip(28), -- generic SLIP + ultra(29), -- ULTRA technologies + ds3(30), -- T-3 + sip(31), -- SMDS + frame-relay(32) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The type of interface, distinguished according to + the physical/link protocol(s) immediately `below' + the network layer in the protocol stack." + ::= { ifEntry 3 } + + ifMtu OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The size of the largest datagram which can be + sent/received on the interface, specified in + octets. For interfaces that are used for + transmitting network datagrams, this is the size + of the largest network datagram that can be sent + on the interface." + ::= { ifEntry 4 } + + ifSpeed OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An estimate of the interface's current bandwidth + in bits per second. For interfaces which do not + vary in bandwidth or for those where no accurate + estimation can be made, this object should contain + the nominal bandwidth." + ::= { ifEntry 5 } + + ifPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The interface's address at the protocol layer + immediately `below' the network layer in the + protocol stack. For interfaces which do not have + + + + + + such an address (e.g., a serial line), this object + should contain an octet string of zero length." + ::= { ifEntry 6 } + + ifAdminStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3) -- in some test mode + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The desired state of the interface. The + testing(3) state indicates that no operational + packets can be passed." + ::= { ifEntry 7 } + + ifOperStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3) -- in some test mode + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The current operational state of the interface. + The testing(3) state indicates that no operational + packets can be passed." + ::= { ifEntry 8 } + + ifLastChange OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the time the interface + entered its current operational state. If the + current state was entered prior to the last re- + initialization of the local network management + subsystem, then this object contains a zero + value." + ::= { ifEntry 9 } + + ifInOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + + + + + + STATUS mandatory + DESCRIPTION + "The total number of octets received on the + interface, including framing characters." + ::= { ifEntry 10 } + + ifInUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of subnetwork-unicast packets + delivered to a higher-layer protocol." + ::= { ifEntry 11 } + + ifInNUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of non-unicast (i.e., subnetwork- + broadcast or subnetwork-multicast) packets + delivered to a higher-layer protocol." + ::= { ifEntry 12 } + + ifInDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of inbound packets which were chosen + to be discarded even though no errors had been + detected to prevent their being deliverable to a + higher-layer protocol. One possible reason for + discarding such a packet could be to free up + buffer space." + ::= { ifEntry 13 } + + ifInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of inbound packets that contained + errors preventing them from being deliverable to a + higher-layer protocol." + ::= { ifEntry 14 } + + + + + + + ifInUnknownProtos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received via the interface + which were discarded because of an unknown or + unsupported protocol." + ::= { ifEntry 15 } + + ifOutOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets transmitted out of the + interface, including framing characters." + ::= { ifEntry 16 } + + ifOutUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets that higher-level + protocols requested be transmitted to a + subnetwork-unicast address, including those that + were discarded or not sent." + ::= { ifEntry 17 } + + ifOutNUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets that higher-level + protocols requested be transmitted to a non- + unicast (i.e., a subnetwork-broadcast or + subnetwork-multicast) address, including those + that were discarded or not sent." + ::= { ifEntry 18 } + + ifOutDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of outbound packets which were chosen + + + + + + to be discarded even though no errors had been + detected to prevent their being transmitted. One + possible reason for discarding such a packet could + be to free up buffer space." + ::= { ifEntry 19 } + + ifOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of outbound packets that could not be + transmitted because of errors." + ::= { ifEntry 20 } + + ifOutQLen OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The length of the output packet queue (in + packets)." + ::= { ifEntry 21 } + + ifSpecific OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A reference to MIB definitions specific to the + particular media being used to realize the + interface. For example, if the interface is + realized by an ethernet, then the value of this + object refers to a document defining objects + specific to ethernet. If this information is not + present, its value should be set to the OBJECT + IDENTIFIER { 0 0 }, which is a syntatically valid + object identifier, and any conformant + implementation of ASN.1 and BER must be able to + generate and recognize this value." + ::= { ifEntry 22 } + + + -- the Address Translation group + + -- Implementation of the Address Translation group is + -- mandatory for all systems. Note however that this group + -- is deprecated by MIB-II. That is, it is being included + + + + + + -- solely for compatibility with MIB-I nodes, and will most + -- likely be excluded from MIB-III nodes. From MIB-II and + -- onwards, each network protocol group contains its own + -- address translation tables. + + -- The Address Translation group contains one table which is + -- the union across all interfaces of the translation tables + -- for converting a NetworkAddress (e.g., an IP address) into + -- a subnetwork-specific address. For lack of a better term, + -- this document refers to such a subnetwork-specific address + -- as a `physical' address. + + -- Examples of such translation tables are: for broadcast + -- media where ARP is in use, the translation table is + -- equivalent to the ARP cache; or, on an X.25 network where + -- non-algorithmic translation to X.121 addresses is + -- required, the translation table contains the + -- NetworkAddress to X.121 address equivalences. + + atTable OBJECT-TYPE + SYNTAX SEQUENCE OF AtEntry + ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "The Address Translation tables contain the + NetworkAddress to `physical' address equivalences. + Some interfaces do not use translation tables for + determining address equivalences (e.g., DDN-X.25 + has an algorithmic method); if all interfaces are + of this type, then the Address Translation table + is empty, i.e., has zero entries." + ::= { at 1 } + + atEntry OBJECT-TYPE + SYNTAX AtEntry + ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "Each entry contains one NetworkAddress to + `physical' address equivalence." + INDEX { atIfIndex, + atNetAddress } + ::= { atTable 1 } + + AtEntry ::= + SEQUENCE { + atIfIndex + INTEGER, + + + + + + atPhysAddress + PhysAddress, + atNetAddress + NetworkAddress + } + + atIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS deprecated + DESCRIPTION + "The interface on which this entry's equivalence + is effective. The interface identified by a + particular value of this index is the same + interface as identified by the same value of + ifIndex." + ::= { atEntry 1 } + + atPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + ACCESS read-write + STATUS deprecated + DESCRIPTION + "The media-dependent `physical' address. + + Setting this object to a null string (one of zero + length) has the effect of invaliding the + corresponding entry in the atTable object. That + is, it effectively dissasociates the interface + identified with said entry from the mapping + identified with said entry. It is an + implementation-specific matter as to whether the + agent removes an invalidated entry from the table. + Accordingly, management stations must be prepared + to receive tabular information from agents that + corresponds to entries not currently in use. + Proper interpretation of such entries requires + examination of the relevant atPhysAddress object." + ::= { atEntry 2 } + + atNetAddress OBJECT-TYPE + SYNTAX NetworkAddress + ACCESS read-write + STATUS deprecated + DESCRIPTION + "The NetworkAddress (e.g., the IP address) + corresponding to the media-dependent `physical' + address." + + + + + + ::= { atEntry 3 } + + + -- the IP group + + -- Implementation of the IP group is mandatory for all + -- systems. + + ipForwarding OBJECT-TYPE + SYNTAX INTEGER { + forwarding(1), -- acting as a gateway + not-forwarding(2) -- NOT acting as a gateway + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The indication of whether this entity is acting + as an IP gateway in respect to the forwarding of + datagrams received by, but not addressed to, this + entity. IP gateways forward datagrams. IP hosts + do not (except those source-routed via the host). + + Note that for some managed nodes, this object may + take on only a subset of the values possible. + Accordingly, it is appropriate for an agent to + return a `badValue' response if a management + station attempts to change this object to an + inappropriate value." + ::= { ip 1 } + + ipDefaultTTL OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The default value inserted into the Time-To-Live + field of the IP header of datagrams originated at + this entity, whenever a TTL value is not supplied + by the transport layer protocol." + ::= { ip 2 } + + ipInReceives OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of input datagrams received from + interfaces, including those received in error." + + + + + + ::= { ip 3 } + + ipInHdrErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input datagrams discarded due to + errors in their IP headers, including bad + checksums, version number mismatch, other format + errors, time-to-live exceeded, errors discovered + in processing their IP options, etc." + ::= { ip 4 } + + ipInAddrErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input datagrams discarded because + the IP address in their IP header's destination + field was not a valid address to be received at + this entity. This count includes invalid + addresses (e.g., 0.0.0.0) and addresses of + unsupported Classes (e.g., Class E). For entities + which are not IP Gateways and therefore do not + forward datagrams, this counter includes datagrams + discarded because the destination address was not + a local address." + ::= { ip 5 } + + ipForwDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input datagrams for which this + entity was not their final IP destination, as a + result of which an attempt was made to find a + route to forward them to that final destination. + In entities which do not act as IP Gateways, this + counter will include only those packets which were + Source-Routed via this entity, and the Source- + Route option processing was successful." + ::= { ip 6 } + + ipInUnknownProtos OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally-addressed datagrams + received successfully but discarded because of an + unknown or unsupported protocol." + ::= { ip 7 } + + ipInDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input IP datagrams for which no + problems were encountered to prevent their + continued processing, but which were discarded + (e.g., for lack of buffer space). Note that this + counter does not include any datagrams discarded + while awaiting re-assembly." + ::= { ip 8 } + + ipInDelivers OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of input datagrams successfully + delivered to IP user-protocols (including ICMP)." + ::= { ip 9 } + + ipOutRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of IP datagrams which local IP + user-protocols (including ICMP) supplied to IP in + requests for transmission. Note that this counter + does not include any datagrams counted in + ipForwDatagrams." + ::= { ip 10 } + + ipOutDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of output IP datagrams for which no + + + + + + problem was encountered to prevent their + transmission to their destination, but which were + discarded (e.g., for lack of buffer space). Note + that this counter would include datagrams counted + in ipForwDatagrams if any such packets met this + (discretionary) discard criterion." + ::= { ip 11 } + + ipOutNoRoutes OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams discarded because no + route could be found to transmit them to their + destination. Note that this counter includes any + packets counted in ipForwDatagrams which meet this + `no-route' criterion. Note that this includes any + datagarms which a host cannot route because all of + its default gateways are down." + ::= { ip 12 } + + ipReasmTimeout OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum number of seconds which received + fragments are held while they are awaiting + reassembly at this entity." + ::= { ip 13 } + + ipReasmReqds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP fragments received which needed + to be reassembled at this entity." + ::= { ip 14 } + + ipReasmOKs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams successfully re- + assembled." + + + + + + ::= { ip 15 } + + ipReasmFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of failures detected by the IP re- + assembly algorithm (for whatever reason: timed + out, errors, etc). Note that this is not + necessarily a count of discarded IP fragments + since some algorithms (notably the algorithm in + RFC 815) can lose track of the number of fragments + by combining them as they are received." + ::= { ip 16 } + + ipFragOKs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams that have been + successfully fragmented at this entity." + ::= { ip 17 } + + ipFragFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams that have been + discarded because they needed to be fragmented at + this entity but could not be, e.g., because their + Don't Fragment flag was set." + ::= { ip 18 } + + ipFragCreates OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagram fragments that have + been generated as a result of fragmentation at + this entity." + ::= { ip 19 } + + + + + + + + + -- the IP address table + + -- The IP address table contains this entity's IP addressing + -- information. + + ipAddrTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpAddrEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The table of addressing information relevant to + this entity's IP addresses." + ::= { ip 20 } + + ipAddrEntry OBJECT-TYPE + SYNTAX IpAddrEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The addressing information for one of this + entity's IP addresses." + INDEX { ipAdEntAddr } + ::= { ipAddrTable 1 } + + IpAddrEntry ::= + SEQUENCE { + ipAdEntAddr + IpAddress, + ipAdEntIfIndex + INTEGER, + ipAdEntNetMask + IpAddress, + ipAdEntBcastAddr + INTEGER, + ipAdEntReasmMaxSize + INTEGER (0..65535) + } + + ipAdEntAddr OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The IP address to which this entry's addressing + information pertains." + ::= { ipAddrEntry 1 } + + + + + + + + ipAdEntIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The index value which uniquely identifies the + interface to which this entry is applicable. The + interface identified by a particular value of this + index is the same interface as identified by the + same value of ifIndex." + ::= { ipAddrEntry 2 } + + ipAdEntNetMask OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The subnet mask associated with the IP address of + this entry. The value of the mask is an IP + address with all the network bits set to 1 and all + the hosts bits set to 0." + ::= { ipAddrEntry 3 } + + ipAdEntBcastAddr OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of the least-significant bit in the IP + broadcast address used for sending datagrams on + the (logical) interface associated with the IP + address of this entry. For example, when the + Internet standard all-ones broadcast address is + used, the value will be 1. This value applies to + both the subnet and network broadcasts addresses + used by the entity on this (logical) interface." + ::= { ipAddrEntry 4 } + + ipAdEntReasmMaxSize OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The size of the largest IP datagram which this + entity can re-assemble from incoming IP fragmented + datagrams received on this interface." + ::= { ipAddrEntry 5 } + + + + + + + -- the IP routing table + + -- The IP routing table contains an entry for each route + -- presently known to this entity. + + ipRouteTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpRouteEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "This entity's IP Routing table." + ::= { ip 21 } + + ipRouteEntry OBJECT-TYPE + SYNTAX IpRouteEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A route to a particular destination." + INDEX { ipRouteDest } + ::= { ipRouteTable 1 } + + IpRouteEntry ::= + SEQUENCE { + ipRouteDest + IpAddress, + ipRouteIfIndex + INTEGER, + ipRouteMetric1 + INTEGER, + ipRouteMetric2 + INTEGER, + ipRouteMetric3 + INTEGER, + ipRouteMetric4 + INTEGER, + ipRouteNextHop + IpAddress, + ipRouteType + INTEGER, + ipRouteProto + INTEGER, + ipRouteAge + INTEGER, + ipRouteMask + IpAddress, + ipRouteMetric5 + INTEGER, + + + + + + ipRouteInfo + OBJECT IDENTIFIER + } + + ipRouteDest OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The destination IP address of this route. An + entry with a value of 0.0.0.0 is considered a + default route. Multiple routes to a single + destination can appear in the table, but access to + such multiple entries is dependent on the table- + access mechanisms defined by the network + management protocol in use." + ::= { ipRouteEntry 1 } + + ipRouteIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The index value which uniquely identifies the + local interface through which the next hop of this + route should be reached. The interface identified + by a particular value of this index is the same + interface as identified by the same value of + ifIndex." + ::= { ipRouteEntry 2 } + + ipRouteMetric1 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The primary routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 3 } + + ipRouteMetric2 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + + + + + + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 4 } + + ipRouteMetric3 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 5 } + + ipRouteMetric4 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 6 } + + ipRouteNextHop OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The IP address of the next hop of this route. + (In the case of a route bound to an interface + which is realized via a broadcast media, the value + of this field is the agent's IP address on that + interface.)" + ::= { ipRouteEntry 7 } + + ipRouteType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + invalid(2), -- an invalidated route + + + + + + -- route to directly + direct(3), -- connected (sub-)network + + -- route to a non-local + indirect(4) -- host/network/sub-network + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The type of route. Note that the values + direct(3) and indirect(4) refer to the notion of + direct and indirect routing in the IP + architecture. + + Setting this object to the value invalid(2) has + the effect of invalidating the corresponding entry + in the ipRouteTable object. That is, it + effectively dissasociates the destination + identified with said entry from the route + identified with said entry. It is an + implementation-specific matter as to whether the + agent removes an invalidated entry from the table. + Accordingly, management stations must be prepared + to receive tabular information from agents that + corresponds to entries not currently in use. + Proper interpretation of such entries requires + examination of the relevant ipRouteType object." + ::= { ipRouteEntry 8 } + + ipRouteProto OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + -- non-protocol information, + -- e.g., manually configured + local(2), -- entries + + -- set via a network + netmgmt(3), -- management protocol + + -- obtained via ICMP, + icmp(4), -- e.g., Redirect + + -- the remaining values are + -- all gateway routing + -- protocols + egp(5), + ggp(6), + + + + + + hello(7), + rip(8), + is-is(9), + es-is(10), + ciscoIgrp(11), + bbnSpfIgp(12), + ospf(13), + bgp(14) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The routing mechanism via which this route was + learned. Inclusion of values for gateway routing + protocols is not intended to imply that hosts + should support those protocols." + ::= { ipRouteEntry 9 } + + ipRouteAge OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The number of seconds since this route was last + updated or otherwise determined to be correct. + Note that no semantics of `too old' can be implied + except through knowledge of the routing protocol + by which the route was learned." + ::= { ipRouteEntry 10 } + + ipRouteMask OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Indicate the mask to be logical-ANDed with the + destination address before being compared to the + value in the ipRouteDest field. For those systems + that do not support arbitrary subnet masks, an + agent constructs the value of the ipRouteMask by + determining whether the value of the correspondent + ipRouteDest field belong to a class-A, B, or C + network, and then using one of: + + mask network + 255.0.0.0 class-A + 255.255.0.0 class-B + 255.255.255.0 class-C + + + + + + If the value of the ipRouteDest is 0.0.0.0 (a + default route), then the mask value is also + 0.0.0.0. It should be noted that all IP routing + subsystems implicitly use this mechanism." + ::= { ipRouteEntry 11 } + + ipRouteMetric5 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 12 } + + ipRouteInfo OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A reference to MIB definitions specific to the + particular routing protocol which is responsible + for this route, as determined by the value + specified in the route's ipRouteProto value. If + this information is not present, its value should + be set to the OBJECT IDENTIFIER { 0 0 }, which is + a syntatically valid object identifier, and any + conformant implementation of ASN.1 and BER must be + able to generate and recognize this value." + ::= { ipRouteEntry 13 } + + + -- the IP Address Translation table + + -- The IP address translation table contain the IpAddress to + -- `physical' address equivalences. Some interfaces do not + -- use translation tables for determining address + -- equivalences (e.g., DDN-X.25 has an algorithmic method); + -- if all interfaces are of this type, then the Address + -- Translation table is empty, i.e., has zero entries. + + ipNetToMediaTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpNetToMediaEntry + ACCESS not-accessible + STATUS mandatory + + + + + + DESCRIPTION + "The IP Address Translation table used for mapping + from IP addresses to physical addresses." + ::= { ip 22 } + + ipNetToMediaEntry OBJECT-TYPE + SYNTAX IpNetToMediaEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Each entry contains one IpAddress to `physical' + address equivalence." + INDEX { ipNetToMediaIfIndex, + ipNetToMediaNetAddress } + ::= { ipNetToMediaTable 1 } + + IpNetToMediaEntry ::= + SEQUENCE { + ipNetToMediaIfIndex + INTEGER, + ipNetToMediaPhysAddress + PhysAddress, + ipNetToMediaNetAddress + IpAddress, + ipNetToMediaType + INTEGER + } + + ipNetToMediaIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The interface on which this entry's equivalence + is effective. The interface identified by a + particular value of this index is the same + interface as identified by the same value of + ifIndex." + ::= { ipNetToMediaEntry 1 } + + ipNetToMediaPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The media-dependent `physical' address." + ::= { ipNetToMediaEntry 2 } + + + + + + + ipNetToMediaNetAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The IpAddress corresponding to the media- + dependent `physical' address." + ::= { ipNetToMediaEntry 3 } + + ipNetToMediaType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + invalid(2), -- an invalidated mapping + dynamic(3), + static(4) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The type of mapping. + + Setting this object to the value invalid(2) has + the effect of invalidating the corresponding entry + in the ipNetToMediaTable. That is, it effectively + dissasociates the interface identified with said + entry from the mapping identified with said entry. + It is an implementation-specific matter as to + whether the agent removes an invalidated entry + from the table. Accordingly, management stations + must be prepared to receive tabular information + from agents that corresponds to entries not + currently in use. Proper interpretation of such + entries requires examination of the relevant + ipNetToMediaType object." + ::= { ipNetToMediaEntry 4 } + + + -- additional IP objects + + ipRoutingDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of routing entries which were chosen + to be discarded even though they are valid. One + possible reason for discarding such an entry could + be to free-up buffer space for other routing + + + + + + entries." + ::= { ip 23 } + + + -- the ICMP group + + -- Implementation of the ICMP group is mandatory for all + -- systems. + + icmpInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ICMP messages which the + entity received. Note that this counter includes + all those counted by icmpInErrors." + ::= { icmp 1 } + + icmpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP messages which the entity + received but determined as having ICMP-specific + errors (bad ICMP checksums, bad length, etc.)." + ::= { icmp 2 } + + icmpInDestUnreachs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Destination Unreachable + messages received." + ::= { icmp 3 } + + icmpInTimeExcds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Time Exceeded messages + received." + ::= { icmp 4 } + + + + + + + + icmpInParmProbs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Parameter Problem messages + received." + ::= { icmp 5 } + + icmpInSrcQuenchs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Source Quench messages + received." + ::= { icmp 6 } + + icmpInRedirects OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Redirect messages received." + ::= { icmp 7 } + + icmpInEchos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo (request) messages + received." + ::= { icmp 8 } + + icmpInEchoReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo Reply messages received." + ::= { icmp 9 } + + icmpInTimestamps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + + + + + + "The number of ICMP Timestamp (request) messages + received." + ::= { icmp 10 } + + icmpInTimestampReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp Reply messages + received." + ::= { icmp 11 } + + icmpInAddrMasks OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Request messages + received." + ::= { icmp 12 } + + icmpInAddrMaskReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Reply messages + received." + ::= { icmp 13 } + + icmpOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ICMP messages which this + entity attempted to send. Note that this counter + includes all those counted by icmpOutErrors." + ::= { icmp 14 } + + icmpOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP messages which this entity did + not send due to problems discovered within ICMP + + + + + + such as a lack of buffers. This value should not + include errors discovered outside the ICMP layer + such as the inability of IP to route the resultant + datagram. In some implementations there may be no + types of error which contribute to this counter's + value." + ::= { icmp 15 } + + icmpOutDestUnreachs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Destination Unreachable + messages sent." + ::= { icmp 16 } + + icmpOutTimeExcds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Time Exceeded messages sent." + ::= { icmp 17 } + + icmpOutParmProbs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Parameter Problem messages + sent." + ::= { icmp 18 } + + icmpOutSrcQuenchs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Source Quench messages sent." + ::= { icmp 19 } + + icmpOutRedirects OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Redirect messages sent. For a + + + + + + host, this object will always be zero, since hosts + do not send redirects." + ::= { icmp 20 } + + icmpOutEchos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo (request) messages sent." + ::= { icmp 21 } + + icmpOutEchoReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo Reply messages sent." + ::= { icmp 22 } + + icmpOutTimestamps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp (request) messages + sent." + ::= { icmp 23 } + + icmpOutTimestampReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp Reply messages + sent." + ::= { icmp 24 } + + icmpOutAddrMasks OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Request messages + sent." + ::= { icmp 25 } + + + + + + + + icmpOutAddrMaskReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Reply messages + sent." + ::= { icmp 26 } + + + -- the TCP group + + -- Implementation of the TCP group is mandatory for all + -- systems that implement the TCP. + + -- Note that instances of object types that represent + -- information about a particular TCP connection are + -- transient; they persist only as long as the connection + -- in question. + + tcpRtoAlgorithm OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + constant(2), -- a constant rto + rsre(3), -- MIL-STD-1778, Appendix B + vanj(4) -- Van Jacobson's algorithm [10] + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The algorithm used to determine the timeout value + used for retransmitting unacknowledged octets." + ::= { tcp 1 } + + tcpRtoMin OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The minimum value permitted by a TCP + implementation for the retransmission timeout, + measured in milliseconds. More refined semantics + for objects of this type depend upon the algorithm + used to determine the retransmission timeout. In + particular, when the timeout algorithm is rsre(3), + an object of this type has the semantics of the + LBOUND quantity described in RFC 793." + + + + + + ::= { tcp 2 } + + + tcpRtoMax OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum value permitted by a TCP + implementation for the retransmission timeout, + measured in milliseconds. More refined semantics + for objects of this type depend upon the algorithm + used to determine the retransmission timeout. In + particular, when the timeout algorithm is rsre(3), + an object of this type has the semantics of the + UBOUND quantity described in RFC 793." + ::= { tcp 3 } + + tcpMaxConn OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The limit on the total number of TCP connections + the entity can support. In entities where the + maximum number of connections is dynamic, this + object should contain the value -1." + ::= { tcp 4 } + + tcpActiveOpens OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the SYN-SENT state from the + CLOSED state." + ::= { tcp 5 } + + tcpPassiveOpens OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the SYN-RCVD state from the + LISTEN state." + ::= { tcp 6 } + + + + + + tcpAttemptFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the CLOSED state from either + the SYN-SENT state or the SYN-RCVD state, plus the + number of times TCP connections have made a direct + transition to the LISTEN state from the SYN-RCVD + state." + ::= { tcp 7 } + + tcpEstabResets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the CLOSED state from either + the ESTABLISHED state or the CLOSE-WAIT state." + ::= { tcp 8 } + + tcpCurrEstab OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of TCP connections for which the + current state is either ESTABLISHED or CLOSE- + WAIT." + ::= { tcp 9 } + + tcpInSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of segments received, including + those received in error. This count includes + segments received on currently established + connections." + ::= { tcp 10 } + + tcpOutSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The total number of segments sent, including + those on current connections but excluding those + containing only retransmitted octets." + ::= { tcp 11 } + + tcpRetransSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of segments retransmitted - that + is, the number of TCP segments transmitted + containing one or more previously transmitted + octets." + ::= { tcp 12 } + + + -- the TCP Connection table + + -- The TCP connection table contains information about this + -- entity's existing TCP connections. + + tcpConnTable OBJECT-TYPE + SYNTAX SEQUENCE OF TcpConnEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A table containing TCP connection-specific + information." + ::= { tcp 13 } + + tcpConnEntry OBJECT-TYPE + SYNTAX TcpConnEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about a particular current TCP + connection. An object of this type is transient, + in that it ceases to exist when (or soon after) + the connection makes the transition to the CLOSED + state." + INDEX { tcpConnLocalAddress, + tcpConnLocalPort, + tcpConnRemAddress, + tcpConnRemPort } + ::= { tcpConnTable 1 } + + + + + + + TcpConnEntry ::= + SEQUENCE { + tcpConnState + INTEGER, + tcpConnLocalAddress + IpAddress, + tcpConnLocalPort + INTEGER (0..65535), + tcpConnRemAddress + IpAddress, + tcpConnRemPort + INTEGER (0..65535) + } + + tcpConnState OBJECT-TYPE + SYNTAX INTEGER { + closed(1), + listen(2), + synSent(3), + synReceived(4), + established(5), + finWait1(6), + finWait2(7), + closeWait(8), + lastAck(9), + closing(10), + timeWait(11), + deleteTCB(12) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The state of this TCP connection. + + The only value which may be set by a management + station is deleteTCB(12). Accordingly, it is + appropriate for an agent to return a `badValue' + response if a management station attempts to set + this object to any other value. + + If a management station sets this object to the + value deleteTCB(12), then this has the effect of + deleting the TCB (as defined in RFC 793) of the + corresponding connection on the managed node, + resulting in immediate termination of the + connection. + + As an implementation-specific option, a RST + + + + + + segment may be sent from the managed node to the + other TCP endpoint (note however that RST segments + are not sent reliably)." + ::= { tcpConnEntry 1 } + + tcpConnLocalAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local IP address for this TCP connection. In + the case of a connection in the listen state which + is willing to accept connections for any IP + interface associated with the node, the value + 0.0.0.0 is used." + ::= { tcpConnEntry 2 } + + tcpConnLocalPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local port number for this TCP connection." + ::= { tcpConnEntry 3 } + + tcpConnRemAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The remote IP address for this TCP connection." + ::= { tcpConnEntry 4 } + + tcpConnRemPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The remote port number for this TCP connection." + ::= { tcpConnEntry 5 } + + + -- additional TCP objects + + tcpInErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The total number of segments received in error + (e.g., bad TCP checksums)." + ::= { tcp 14 } + + tcpOutRsts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of TCP segments sent containing the + RST flag." + ::= { tcp 15 } + + + -- the UDP group + + -- Implementation of the UDP group is mandatory for all + -- systems which implement the UDP. + + udpInDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of UDP datagrams delivered to + UDP users." + ::= { udp 1 } + + udpNoPorts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of received UDP datagrams for + which there was no application at the destination + port." + ::= { udp 2 } + + udpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of received UDP datagrams that could + not be delivered for reasons other than the lack + of an application at the destination port." + ::= { udp 3 } + + + + + + udpOutDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of UDP datagrams sent from this + entity." + ::= { udp 4 } + + + -- the UDP Listener table + + -- The UDP listener table contains information about this + -- entity's UDP end-points on which a local application is + -- currently accepting datagrams. + + udpTable OBJECT-TYPE + SYNTAX SEQUENCE OF UdpEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A table containing UDP listener information." + ::= { udp 5 } + + udpEntry OBJECT-TYPE + SYNTAX UdpEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about a particular current UDP + listener." + INDEX { udpLocalAddress, udpLocalPort } + ::= { udpTable 1 } + + UdpEntry ::= + SEQUENCE { + udpLocalAddress + IpAddress, + udpLocalPort + INTEGER (0..65535) + } + + udpLocalAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local IP address for this UDP listener. In + + + + + + the case of a UDP listener which is willing to + accept datagrams for any IP interface associated + with the node, the value 0.0.0.0 is used." + ::= { udpEntry 1 } + + udpLocalPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local port number for this UDP listener." + ::= { udpEntry 2 } + + + -- the EGP group + + -- Implementation of the EGP group is mandatory for all + -- systems which implement the EGP. + + egpInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received without + error." + ::= { egp 1 } + + egpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received that proved + to be in error." + ::= { egp 2 } + + egpOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of locally generated EGP + messages." + ::= { egp 3 } + + egpOutErrors OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally generated EGP messages not + sent due to resource limitations within an EGP + entity." + ::= { egp 4 } + + + -- the EGP Neighbor table + + -- The EGP neighbor table contains information about this + -- entity's EGP neighbors. + + egpNeighTable OBJECT-TYPE + SYNTAX SEQUENCE OF EgpNeighEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The EGP neighbor table." + ::= { egp 5 } + + egpNeighEntry OBJECT-TYPE + SYNTAX EgpNeighEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about this entity's relationship with + a particular EGP neighbor." + INDEX { egpNeighAddr } + ::= { egpNeighTable 1 } + + EgpNeighEntry ::= + SEQUENCE { + egpNeighState + INTEGER, + egpNeighAddr + IpAddress, + egpNeighAs + INTEGER, + egpNeighInMsgs + Counter, + egpNeighInErrs + Counter, + egpNeighOutMsgs + Counter, + egpNeighOutErrs + Counter, + + + + + + egpNeighInErrMsgs + Counter, + egpNeighOutErrMsgs + Counter, + egpNeighStateUps + Counter, + egpNeighStateDowns + Counter, + egpNeighIntervalHello + INTEGER, + egpNeighIntervalPoll + INTEGER, + egpNeighMode + INTEGER, + egpNeighEventTrigger + INTEGER + } + + egpNeighState OBJECT-TYPE + SYNTAX INTEGER { + idle(1), + acquisition(2), + down(3), + up(4), + cease(5) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The EGP state of the local system with respect to + this entry's EGP neighbor. Each EGP state is + represented by a value that is one greater than + the numerical value associated with said state in + RFC 904." + ::= { egpNeighEntry 1 } + + egpNeighAddr OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The IP address of this entry's EGP neighbor." + ::= { egpNeighEntry 2 } + + egpNeighAs OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The autonomous system of this EGP peer. Zero + should be specified if the autonomous system + number of the neighbor is not yet known." + ::= { egpNeighEntry 3 } + + egpNeighInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received without error + from this EGP peer." + ::= { egpNeighEntry 4 } + + egpNeighInErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received from this EGP + peer that proved to be in error (e.g., bad EGP + checksum)." + ::= { egpNeighEntry 5 } + + egpNeighOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally generated EGP messages to + this EGP peer." + ::= { egpNeighEntry 6 } + + egpNeighOutErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally generated EGP messages not + sent to this EGP peer due to resource limitations + within an EGP entity." + ::= { egpNeighEntry 7 } + + egpNeighInErrMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The number of EGP-defined error messages received + from this EGP peer." + ::= { egpNeighEntry 8 } + + egpNeighOutErrMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP-defined error messages sent to + this EGP peer." + ::= { egpNeighEntry 9 } + + egpNeighStateUps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP state transitions to the UP + state with this EGP peer." + ::= { egpNeighEntry 10 } + + egpNeighStateDowns OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP state transitions from the UP + state to any other state with this EGP peer." + ::= { egpNeighEntry 11 } + + egpNeighIntervalHello OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The interval between EGP Hello command + retransmissions (in hundredths of a second). This + represents the t1 timer as defined in RFC 904." + ::= { egpNeighEntry 12 } + + egpNeighIntervalPoll OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The interval between EGP poll command + + + + + + retransmissions (in hundredths of a second). This + represents the t3 timer as defined in RFC 904." + ::= { egpNeighEntry 13 } + + egpNeighMode OBJECT-TYPE + SYNTAX INTEGER { active(1), passive(2) } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The polling mode of this EGP entity, either + passive or active." + ::= { egpNeighEntry 14 } + + egpNeighEventTrigger OBJECT-TYPE + SYNTAX INTEGER { start(1), stop(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A control variable used to trigger operator- + initiated Start and Stop events. When read, this + variable always returns the most recent value that + egpNeighEventTrigger was set to. If it has not + been set since the last initialization of the + network management subsystem on the node, it + returns a value of `stop'. + + When set, this variable causes a Start or Stop + event on the specified neighbor, as specified on + pages 8-10 of RFC 904. Briefly, a Start event + causes an Idle peer to begin neighbor acquisition + and a non-Idle peer to reinitiate neighbor + acquisition. A stop event causes a non-Idle peer + to return to the Idle state until a Start event + occurs, either via egpNeighEventTrigger or + otherwise." + ::= { egpNeighEntry 15 } + + + -- additional EGP objects + + egpAs OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The autonomous system number of this EGP entity." + ::= { egp 6 } + + + + + + + -- the Transmission group + + -- Based on the transmission media underlying each interface + -- on a system, the corresponding portion of the Transmission + -- group is mandatory for that system. + + -- When Internet-standard definitions for managing + -- transmission media are defined, the transmission group is + -- used to provide a prefix for the names of those objects. + + -- Typically, such definitions reside in the experimental + -- portion of the MIB until they are "proven", then as a + -- part of the Internet standardization process, the + -- definitions are accordingly elevated and a new object + -- identifier, under the transmission group is defined. By + -- convention, the name assigned is: + -- + -- type OBJECT IDENTIFIER ::= { transmission number } + -- + -- where "type" is the symbolic value used for the media in + -- the ifType column of the ifTable object, and "number" is + -- the actual integer value corresponding to the symbol. + + + -- the SNMP group + + -- Implementation of the SNMP group is mandatory for all + -- systems which support an SNMP protocol entity. Some of + -- the objects defined below will be zero-valued in those + -- SNMP implementations that are optimized to support only + -- those functions specific to either a management agent or + -- a management station. In particular, it should be + -- observed that the objects below refer to an SNMP entity, + -- and there may be several SNMP entities residing on a + -- managed node (e.g., if the node is hosting acting as + -- a management station). + + snmpInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of Messages delivered to the + SNMP entity from the transport service." + ::= { snmp 1 } + + snmpOutPkts OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + passed from the SNMP protocol entity to the + transport service." + ::= { snmp 2 } + + snmpInBadVersions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + delivered to the SNMP protocol entity and were for + an unsupported SNMP version." + ::= { snmp 3 } + + snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which used a SNMP + community name not known to said entity." + ::= { snmp 4 } + + snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which represented an SNMP + operation which was not allowed by the SNMP + community named in the Message." + ::= { snmp 5 } + + snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ASN.1 or BER errors + encountered by the SNMP protocol entity when + decoding received SNMP Messages." + ::= { snmp 6 } + + + + + + -- { snmp 7 } is not used + + snmpInTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `tooBig'." + ::= { snmp 8 } + + snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `noSuchName'." + ::= { snmp 9 } + + snmpInBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 10 } + + snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number valid SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `readOnly'. It should be noted that it is a + protocol error to generate an SNMP PDU which + contains the value `readOnly' in the error-status + field, as such this object is provided as a means + of detecting incorrect implementations of the + + + + + + SNMP." + ::= { snmp 11 } + + snmpInGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 12 } + + snmpInTotalReqVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + retrieved successfully by the SNMP protocol entity + as the result of receiving valid SNMP Get-Request + and Get-Next PDUs." + ::= { snmp 13 } + + snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + altered successfully by the SNMP protocol entity + as the result of receiving valid SNMP Set-Request + PDUs." + ::= { snmp 14 } + + snmpInGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 15 } + + snmpInGetNexts OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 16 } + + snmpInSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 17 } + + snmpInGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 18 } + + snmpInTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 19 } + + snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `tooBig.'" + ::= { snmp 20 } + + + + + + snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status is + `noSuchName'." + ::= { snmp 21 } + + snmpOutBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 22 } + + -- { snmp 23 } is not used + + snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 24 } + + snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 25 } + + snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 26 } + + snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 27 } + + snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 28 } + + snmpOutTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 29 } + + snmpEnableAuthenTraps OBJECT-TYPE + SYNTAX INTEGER { enabled(1), disabled(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Indicates whether the SNMP agent process is + permitted to generate authentication-failure + traps. The value of this object overrides any + configuration information; as such, it provides a + means whereby all authentication-failure traps may + be disabled. + + Note that it is strongly recommended that this + object be stored in non-volatile memory so that it + remains constant between re-initializations of the + network management system." + + + + + + ::= { snmp 30 } + + END + diff --git a/lib/snmp/test/snmp_test_data/SA-MIB.funcs b/lib/snmp/test/snmp_test_data/SA-MIB.funcs new file mode 100644 index 0000000000..71757beb6f --- /dev/null +++ b/lib/snmp/test/snmp_test_data/SA-MIB.funcs @@ -0,0 +1,5 @@ +{saBadValue, {sa, sa_bad_value, []}}. +{saGenErr, {sa, sa_gen_err, []}}. +{saTooBig, {sa, sa_too_big, []}}. +{saFel, {sa, sa_fel, []}}. +{saTest, {snmp_generic, variable_func, [{saTest, volatile}]}}. diff --git a/lib/snmp/test/snmp_test_data/SA-MIB.mib b/lib/snmp/test/snmp_test_data/SA-MIB.mib new file mode 100644 index 0000000000..c5953ee17c --- /dev/null +++ b/lib/snmp/test/snmp_test_data/SA-MIB.mib @@ -0,0 +1,93 @@ +SA-MIB DEFINITIONS ::= BEGIN + + IMPORTS + Counter, TimeTicks, IpAddress + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212 + mgmt, NetworkAddress, IpAddress, Counter, Gauge, + TimeTicks, enterprises + FROM RFC1155-SMI + DisplayString, mib-2 + FROM RFC1213-MIB + sysContact + FROM STANDARD-MIB + OBJECT-TYPE + FROM RFC-1212 + intViewSubtree + FROM OLD-SNMPEA-MIB; + + +ericsson OBJECT IDENTIFIER ::= {enterprises 193} +sa OBJECT IDENTIFIER ::= { ericsson 2 } + + + saTest OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + should include the full name and version + identification of the system's hardware type, + software operating-system, and networking + software. It is mandatory that this only contain + printable ASCII characters." + ::= { sa 1 } + + + saBadValue OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The instrum is_set_ok will return badValue" + ::= { sa 2 } + + saGenErr OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The instrum set will return genErr" + ::= { sa 3 } + + saTooBig OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The instrum get will return a 500 byte list" + ::= { sa 4 } + + saFel OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The instrumget will return undefined" + ::= { sa 5 } + + + saTrap TRAP-TYPE + ENTERPRISE ericsson + VARIABLES { sysContact, saTest } + DESCRIPTION + "A linkUp trap signifies that the sending + protocol entity recognizes that one of the + communication links represented in the agent's + configuration has come up." + ::= 1 + + saTrap2 TRAP-TYPE + ENTERPRISE ericsson + VARIABLES { sysContact, saTest, intViewSubtree } + DESCRIPTION + "A linkUp trap signifies that the sending + protocol entity recognizes that one of the + communication links represented in the agent's + configuration has come up." + ::= 2 + + +END diff --git a/lib/snmp/test/snmp_test_data/SNMPv2-MIB.funcs b/lib/snmp/test/snmp_test_data/SNMPv2-MIB.funcs new file mode 100644 index 0000000000..8fe25bb477 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/SNMPv2-MIB.funcs @@ -0,0 +1,28 @@ +%% The system group +{sysUpTime, {snmp_standard_mib, sys_up_time, []}}. +{sysDescr, {snmp_generic, variable_func, [{sysDescr, permanent}]}}. +{sysObjectID, {snmp_generic, variable_func, [{sysObjectID, permanent}]}}. +{sysContact, {snmp_generic, variable_func, [{sysContact, permanent}]}}. +{sysName, {snmp_generic, variable_func, [{sysName, permanent}]}}. +{sysLocation, {snmp_generic, variable_func, [{sysLocation, permanent}]}}. +{sysServices, {snmp_generic, variable_func, [{sysServices, permanent}]}}. + +{sysORLastChange, {snmp_generic, variable_func, [{sysORLastChange, volatile}]}}. +{sysORTable, {snmp_standard_mib, sys_or_table, []}}. + +%% Snmp special objects +{snmpEnableAuthenTraps, {snmp_standard_mib, snmp_enable_authen_traps, []}}. +{snmpSetSerialNo, {snmp_standard_mib, snmp_set_serial_no, []}}. + +%% Counters +{snmpInPkts, {snmp_standard_mib, variable_func, [snmpInPkts]}}. +{snmpInBadVersions, {snmp_standard_mib, variable_func, [snmpInBadVersions]}}. +{snmpInBadCommunityNames, {snmp_standard_mib, variable_func, [snmpInBadCommunityNames]}}. +{snmpInBadCommunityUses, {snmp_standard_mib, variable_func, [snmpInBadCommunityUses]}}. +{snmpInASNParseErrs, {snmp_standard_mib, variable_func, [snmpInASNParseErrs]}}. +{snmpProxyDrops, {snmp_standard_mib, variable_func, [snmpProxyDrops]}}. +{snmpSilentDrops, {snmp_standard_mib, variable_func, [snmpSilentDrops]}}. + +%% Dummy objects, included in notifications +{snmpTrapEnterprise, {snmp_standard_mib, dummy, []}}. +{snmpTrapOID, {snmp_standard_mib, dummy, []}}. diff --git a/lib/snmp/test/snmp_test_data/SNMPv2-MIB.mib b/lib/snmp/test/snmp_test_data/SNMPv2-MIB.mib new file mode 100644 index 0000000000..e45d9d91da --- /dev/null +++ b/lib/snmp/test/snmp_test_data/SNMPv2-MIB.mib @@ -0,0 +1,767 @@ +SNMPv2-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2 + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF; + +snmpMIB MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "IETF SNMPv2 Working Group" + CONTACT-INFO + " Marshall T. Rose + + Postal: Dover Beach Consulting, Inc. + 420 Whisman Court + Mountain View, CA 94043-2186 + US + + Tel: +1 415 968 1052 + + E-mail: [email protected]" + DESCRIPTION + "The MIB module for SNMPv2 entities." + REVISION "9304010000Z" + DESCRIPTION + "The initial revision of this MIB module was published as + RFC 1450." + ::= { snmpModules 1 } + + +snmpMIBObjects OBJECT IDENTIFIER ::= { snmpMIB 1 } + +-- ::= { snmpMIBObjects 1 } this OID is obsolete +-- ::= { snmpMIBObjects 2 } this OID is obsolete +-- ::= { snmpMIBObjects 3 } this OID is obsolete + + +-- the System group +-- +-- a collection of objects common to all managed systems. + +system OBJECT IDENTIFIER ::= { mib-2 1 } + +sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the entity. This value should + include the full name and version identification of the + system's hardware type, software operating-system, and + networking software." + ::= { system 1 } + +sysObjectID OBJECT-TYPE + + + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The vendor's authoritative identification of the network + management subsystem contained in the entity. This value is + allocated within the SMI enterprises subtree (1.3.6.1.4.1) + and provides an easy and unambiguous means for determining + `what kind of box' is being managed. For example, if vendor + `Flintstones, Inc.' was assigned the subtree + 1.3.6.1.4.1.4242, it could assign the identifier + 1.3.6.1.4.1.4242.1.1 to its `Fred Router'." + ::= { system 2 } + +sysUpTime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The time (in hundredths of a second) since the network + management portion of the system was last re-initialized." + ::= { system 3 } + +sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The textual identification of the contact person for this + managed node, together with information on how to contact + this person. If no contact information is known, the value + is the zero-length string." + ::= { system 4 } + +sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An administratively-assigned name for this managed node. + By convention, this is the node's fully-qualified domain + name. If the name is unknown, the value is the zero-length + string." + ::= { system 5 } + +sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The physical location of this node (e.g., `telephone + closet, 3rd floor'). If the location is unknown, the value + is the zero-length string." + ::= { system 6 } + +sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A value which indicates the set of services that this + entity may potentially offers. The value is a sum. This + sum initially takes the value zero, Then, for each layer, L, + in the range 1 through 7, that this node performs + transactions for, 2 raised to (L - 1) is added to the sum. + For example, a node which performs only routing functions + would have a value of 4 (2^(3-1)). In contrast, a node + which is a host offering application services would have a + value of 72 (2^(4-1) + 2^(7-1)). Note that in the context + of the Internet suite of protocols, values should be + calculated accordingly: + + layer functionality + 1 physical (e.g., repeaters) + 2 datalink/subnetwork (e.g., bridges) + 3 internet (e.g., supports the IP) + 4 end-to-end (e.g., supports the TCP) + 7 applications (e.g., supports the SMTP) + + For systems including OSI protocols, layers 5 and 6 may also + be counted." + ::= { system 7 } + + +-- object resource information +-- +-- a collection of objects which describe the SNMPv2 entity's +-- (statically and dynamically configurable) support of +-- various MIB modules. + +sysORLastChange OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time of the most recent + change in state or value of any instance of sysORID." + ::= { system 8 } + +sysORTable OBJECT-TYPE + SYNTAX SEQUENCE OF SysOREntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The (conceptual) table listing the capabilities of the + local SNMPv2 entity acting in an agent role with respect to + various MIB modules. SNMPv2 entities having dynamically- + configurable support of MIB modules will have a + dynamically-varying number of conceptual rows." + ::= { system 9 } + +sysOREntry OBJECT-TYPE + SYNTAX SysOREntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { sysORIndex } + ::= { sysORTable 1 } + +SysOREntry ::= SEQUENCE { + sysORIndex INTEGER, + sysORID OBJECT IDENTIFIER, + sysORDescr DisplayString, + sysORUpTime TimeStamp +} + +sysORIndex OBJECT-TYPE + SYNTAX INTEGER (1..2147483647) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { sysOREntry 1 } + +sysORID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An authoritative identification of a capabilities statement + with respect to various MIB modules supported by the local + SNMPv2 entity acting in an agent role." + + ::= { sysOREntry 2 } + +sysORDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { sysOREntry 3 } + +sysORUpTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time this conceptual row was + last instanciated." + ::= { sysOREntry 4 } + + +-- the SNMP group +-- +-- a collection of objects providing basic instrumentation and +-- control of an SNMP entity. + +snmp OBJECT IDENTIFIER ::= { mib-2 11 } + +snmpInPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of messages delivered to the SNMP entity + from the transport service." + ::= { snmp 1 } + +snmpInBadVersions OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages which were delivered to + the SNMP entity and were for an unsupported SNMP version." + ::= { snmp 3 } + +snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages delivered to the SNMP + entity which used a SNMP community name not known to said + entity." + ::= { snmp 4 } + +snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages delivered to the SNMP + entity which represented an SNMP operation which was not + allowed by the SNMP community named in the message." + ::= { snmp 5 } + +snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of ASN.1 or BER errors encountered by the + SNMP entity when decoding received SNMP messages." + ::= { snmp 6 } + +snmpEnableAuthenTraps OBJECT-TYPE + SYNTAX INTEGER { enabled(1), disabled(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Indicates whether the SNMP entity is permitted to generate + authenticationFailure traps. The value of this object + overrides any configuration information; as such, it + provides a means whereby all authenticationFailure traps may + be disabled. + + Note that it is strongly recommended that this object be + stored in non-volatile memory so that it remains constant + across re-initializations of the network management system." + ::= { snmp 30 } + +snmpSilentDrops OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of GetRequest-PDUs, GetNextRequest-PDUs, + GetBulkRequest-PDUs, SetRequest-PDUs, and InformRequest-PDUs + delivered to the SNMP entity which were silently dropped + because the size of a reply containing an alternate + Response-PDU with an empty variable-bindings field was + greater than either a local constraint or the maximum + message size associated with the originator of the request." + ::= { snmp 31 } + +snmpProxyDrops OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of GetRequest-PDUs, GetNextRequest-PDUs, + GetBulkRequest-PDUs, SetRequest-PDUs, and InformRequest-PDUs + delivered to the SNMP entity which were silently dropped + because the transmission of the (possibly translated) + message to a proxy target failed in a manner (other than a + time-out) such that no Response-PDU could be returned." + ::= { snmp 32 } + + +-- information for notifications +-- +-- a collection of objects which allow the SNMPv2 entity, when +-- acting in an agent role, to be configured to generate +-- SNMPv2-Trap-PDUs. + +snmpTrap OBJECT IDENTIFIER ::= { snmpMIBObjects 4 } + + +snmpTrapOID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS accessible-for-notify + STATUS current + DESCRIPTION + "The authoritative identification of the notification + currently being sent. This variable occurs as the second + varbind in every SNMPv2-Trap-PDU and InformRequest-PDU." + ::= { snmpTrap 1 } + +-- ::= { snmpTrap 2 } this OID is obsolete + +snmpTrapEnterprise OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS accessible-for-notify + STATUS current + DESCRIPTION + "The authoritative identification of the enterprise + associated with the trap currently being sent. When a + SNMPv2 proxy agent is mapping an RFC1157 Trap-PDU into a + SNMPv2-Trap-PDU, this variable occurs as the last varbind." + ::= { snmpTrap 3 } + +-- ::= { snmpTrap 4 } this OID is obsolete + + +-- well-known traps + +snmpTraps OBJECT IDENTIFIER ::= { snmpMIBObjects 5 } + +coldStart NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "A coldStart trap signifies that the SNMPv2 entity, acting + in an agent role, is reinitializing itself and that its + configuration may have been altered." + ::= { snmpTraps 1 } + +warmStart NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "A warmStart trap signifies that the SNMPv2 entity, acting + in an agent role, is reinitializing itself such that its + configuration is unaltered." + ::= { snmpTraps 2 } + +-- Note the linkDown NOTIFICATION-TYPE ::= { snmpTraps 3 } +-- and the linkUp NOTIFICATION-TYPE ::= { snmpTraps 4 } +-- are defined in RFC 1573 + +authenticationFailure NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "An authenticationFailure trap signifies that the SNMPv2 + entity, acting in an agent role, has received a protocol + message that is not properly authenticated. While all + implementations of the SNMPv2 must be capable of generating + this trap, the snmpEnableAuthenTraps object indicates + whether this trap will be generated." + ::= { snmpTraps 5 } + +-- Note the egpNeighborLoss NOTIFICATION-TYPE ::= { snmpTraps 6 } +-- is defined in RFC 1213 +-- the set group +-- +-- a collection of objects which allow several cooperating +-- SNMPv2 entities, all acting in a manager role, to +-- coordinate their use of the SNMPv2 set operation. + +snmpSet OBJECT IDENTIFIER ::= { snmpMIBObjects 6 } + + +snmpSetSerialNo OBJECT-TYPE + SYNTAX TestAndIncr + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An advisory lock used to allow several cooperating SNMPv2 + entities, all acting in a manager role, to coordinate their + use of the SNMPv2 set operation. + + This object is used for coarse-grain coordination. To + achieve fine-grain coordination, one or more similar objects + might be defined within each MIB group, as appropriate." + ::= { snmpSet 1 } + + +-- conformance information + +snmpMIBConformance + OBJECT IDENTIFIER ::= { snmpMIB 2 } + +snmpMIBCompliances + OBJECT IDENTIFIER ::= { snmpMIBConformance 1 } +snmpMIBGroups OBJECT IDENTIFIER ::= { snmpMIBConformance 2 } + + +-- compliance statements + +-- ::= { snmpMIBCompliances 1 } this OID is obsolete + +snmpBasicCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for SNMPv2 entities which + implement the SNMPv2 MIB." + MODULE -- this module + MANDATORY-GROUPS { snmpGroup, snmpSetGroup, systemGroup, + snmpBasicNotificationsGroup } + + GROUP snmpCommunityGroup + DESCRIPTION + "This group is mandatory for SNMPv2 entities which + support community-based authentication." + + ::= { snmpMIBCompliances 2 } + + +-- units of conformance + +-- ::= { snmpMIBGroups 1 } this OID is obsolete +-- ::= { snmpMIBGroups 2 } this OID is obsolete +-- ::= { snmpMIBGroups 3 } this OID is obsolete +-- ::= { snmpMIBGroups 4 } this OID is obsolete + +snmpGroup OBJECT-GROUP + OBJECTS { snmpInPkts, + snmpInBadVersions, + snmpInASNParseErrs, + snmpSilentDrops, + snmpProxyDrops, + snmpEnableAuthenTraps } + STATUS current + DESCRIPTION + "A collection of objects providing basic instrumentation and + control of an SNMPv2 entity." + ::= { snmpMIBGroups 8 } + +snmpCommunityGroup OBJECT-GROUP + OBJECTS { snmpInBadCommunityNames, + snmpInBadCommunityUses } + STATUS current + DESCRIPTION + "A collection of objects providing basic instrumentation of + a SNMPv2 entity which supports community-based + authentication." + ::= { snmpMIBGroups 9 } + +snmpSetGroup OBJECT-GROUP + OBJECTS { snmpSetSerialNo } + STATUS current + DESCRIPTION + "A collection of objects which allow several cooperating + SNMPv2 entities, all acting in a manager role, to coordinate + their use of the SNMPv2 set operation." + ::= { snmpMIBGroups 5 } + +systemGroup OBJECT-GROUP + OBJECTS { sysDescr, sysObjectID, sysUpTime, + sysContact, sysName, sysLocation, + sysServices, + sysORLastChange, sysORID, + sysORUpTime, sysORDescr } + STATUS current + DESCRIPTION + "The system group defines objects which are common to all + managed systems." + ::= { snmpMIBGroups 6 } + +snmpBasicNotificationsGroup NOTIFICATION-GROUP + NOTIFICATIONS { coldStart, authenticationFailure } + STATUS current + DESCRIPTION + "The two notifications which an SNMPv2 entity is required to + implement." + ::= { snmpMIBGroups 7 } + + +-- definitions in RFC 1213 made obsolete by the inclusion of a +-- subset of the snmp group in this MIB + +snmpOutPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Messages which were + passed from the SNMP protocol entity to the + transport service." + ::= { snmp 2 } + +-- { snmp 7 } is not used + +snmpInTooBigs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `tooBig'." + ::= { snmp 8 } + +snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `noSuchName'." + ::= { snmp 9 } + +snmpInBadValues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 10 } + +snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number valid SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `readOnly'. It should be noted that it is a + protocol error to generate an SNMP PDU which + contains the value `readOnly' in the error-status + field, as such this object is provided as a means + of detecting incorrect implementations of the + SNMP." + ::= { snmp 11 } + +snmpInGenErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 12 } + +snmpInTotalReqVars OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of MIB objects which have been + retrieved successfully by the SNMP protocol entity + as the result of receiving valid SNMP Get-Request + and Get-Next PDUs." + ::= { snmp 13 } + +snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of MIB objects which have been + altered successfully by the SNMP protocol entity + as the result of receiving valid SNMP Set-Request + PDUs." + ::= { snmp 14 } + +snmpInGetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 15 } + +snmpInGetNexts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 16 } + +snmpInSetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 17 } + +snmpInGetResponses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 18 } + +snmpInTraps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 19 } + +snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `tooBig.'" + ::= { snmp 20 } + +snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status is + `noSuchName'." + ::= { snmp 21 } + +snmpOutBadValues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 22 } + + +-- { snmp 23 } is not used + +snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 24 } + +snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 25 } + +snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 26 } + +snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 27 } + +snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 28 } + +snmpOutTraps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 29 } + +snmpObsoleteGroup OBJECT-GROUP + OBJECTS { snmpOutPkts, snmpInTooBigs, snmpInNoSuchNames, + snmpInBadValues, snmpInReadOnlys, snmpInGenErrs, + snmpInTotalReqVars, snmpInTotalSetVars, + snmpInGetRequests, snmpInGetNexts, snmpInSetRequests, + snmpInGetResponses, snmpInTraps, snmpOutTooBigs, + snmpOutNoSuchNames, snmpOutBadValues, snmpOutGenErrs, + snmpOutGetRequests, snmpOutGetNexts, snmpOutSetRequests, + snmpOutGetResponses, snmpOutTraps } + STATUS obsolete + DESCRIPTION + "A collection of objects from RFC 1213 made obsolete by this + MIB." + ::= { snmpMIBGroups 10 } + +END diff --git a/lib/snmp/test/snmp_test_data/STANDARD-MIB.funcs b/lib/snmp/test/snmp_test_data/STANDARD-MIB.funcs new file mode 100644 index 0000000000..a0b105c2fd --- /dev/null +++ b/lib/snmp/test/snmp_test_data/STANDARD-MIB.funcs @@ -0,0 +1,8 @@ +{sysUpTime, {snmp_standard_mib, sys_up_time, []}}. +{sysDescr, {snmp_generic, variable_func, [{sysDescr, permanent}]}}. +{sysObjectID, {snmp_generic, variable_func, [{sysObjectID, permanent}]}}. +{sysContact, {snmp_generic, variable_func, [{sysContact, permanent}]}}. +{sysName, {snmp_generic, variable_func, [{sysName, permanent}]}}. +{sysLocation, {snmp_generic, variable_func, [{sysLocation, permanent}]}}. +{sysServices, {snmp_generic, variable_func, [{sysServices, permanent}]}}. +{snmpEnableAuthenTraps, {snmp_standard_mib, snmp_enable_authen_traps, []}}. diff --git a/lib/snmp/test/snmp_test_data/STANDARD-MIB.mib b/lib/snmp/test/snmp_test_data/STANDARD-MIB.mib new file mode 100644 index 0000000000..552b8a3e48 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/STANDARD-MIB.mib @@ -0,0 +1,528 @@ +STANDARD-MIB DEFINITIONS ::= BEGIN + + IMPORTS + Counter, TimeTicks + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212 + DisplayString, mib-2 + FROM RFC1213-MIB + ; + + +-- Standard Datatypes + +-- From SNMPv2 (rfc1903) +TruthValue ::= +-- Represents a boolean value + INTEGER { true(1), false(2) } + +-- From SNMPv2 (rfc1903) +DateAndTime ::= +-- DESCRIPTION +-- "A date-time specification. +-- +-- field octets contents range +-- 1 1-2 year 0..65536 +-- 2 3 month 1..12 +-- 3 4 day 1..31 +-- 4 5 hour 0..23 +-- 5 6 minutes 0..59 +-- 6 7 seconds 0..60 +-- (use 60 for leap-second) +-- 7 8 deci-seconds 0..9 +-- 8 9 direction from UTC '+' / '-' +-- 9 10 hours from UTC 0..11 +-- 10 11 minutes from UTC 0..59 +-- +-- For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be +-- displayed as: +-- +-- 1992-5-26,13:30:15.0,-4:0 +-- +-- Note that if only local time is known, then timezone +-- information (fields 8-10) is not present." + OCTET STRING (SIZE (8 | 11)) + +-- From SNMPv2 (rfc1903) +RowStatus ::= + INTEGER { + -- the following two values are states: + -- these values may be read or written + active(1), + notInService(2), + + -- the following value is a state: + -- this value may be read, but not written + notReady(3), + + -- the following three values are + -- actions: these values may be written, + -- but are never read + createAndGo(4), + createAndWait(5), + destroy(6) + } + + +system OBJECT IDENTIFIER ::= { mib-2 1 } +snmp OBJECT IDENTIFIER ::= { mib-2 11 } + + +-- the System group + +-- Implementation of the System group is mandatory for all +-- systems. If an agent is not configured to have a value +-- for any of these variables, a string of length 0 is +-- returned. + +sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + should include the full name and version + identification of the system's hardware type, + software operating-system, and networking + software. It is mandatory that this only contain + printable ASCII characters." + ::= { system 1 } + +sysObjectID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The vendor's authoritative identification of the + network management subsystem contained in the + entity. This value is allocated within the SMI + enterprises subtree (1.3.6.1.4.1) and provides an + easy and unambiguous means for determining `what + kind of box' is being managed. For example, if + vendor `Flintstones, Inc.' was assigned the + subtree 1.3.6.1.4.1.4242, it could assign the + identifier 1.3.6.1.4.1.4242.1.1 to its `Fred + Router'." + ::= { system 2 } + +sysUpTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The time (in hundredths of a second) since the + network management portion of the system was last + re-initialized." + ::= { system 3 } + +sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The textual identification of the contact person + for this managed node, together with information + on how to contact this person." + ::= { system 4 } + +sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An administratively-assigned name for this + managed node. By convention, this is the node's + fully-qualified domain name." + ::= { system 5 } + +sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The physical location of this node (e.g., + `telephone closet, 3rd floor')." + ::= { system 6 } + +sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A value which indicates the set of services that + this entity primarily offers. + + The value is a sum. This sum initially takes the + value zero, Then, for each layer, L, in the range + 1 through 7, that this node performs transactions + for, 2 raised to (L - 1) is added to the sum. For + example, a node which performs primarily routing + functions would have a value of 4 (2^(3-1)). In + contrast, a node which is a host offering + application services would have a value of 72 + (2^(4-1) + 2^(7-1)). Note that in the context of + the Internet suite of protocols, values should be + calculated accordingly: + + layer functionality + 1 physical (e.g., repeaters) + 2 datalink/subnetwork (e.g., bridges) + 3 internet (e.g., IP gateways) + 4 end-to-end (e.g., IP hosts) + 7 applications (e.g., mail relays) + + For systems including OSI protocols, layers 5 and + 6 may also be counted." + ::= { system 7 } + + + -- the SNMP group + + -- Implementation of the SNMP group is mandatory for all + -- systems which support an SNMP protocol entity. Some of + -- the objects defined below will be zero-valued in those + -- SNMP implementations that are optimized to support only + -- those functions specific to either a management agent or + -- a management station. In particular, it should be + -- observed that the objects below refer to an SNMP entity, + -- and there may be several SNMP entities residing on a + -- managed node (e.g., if the node is hosting acting as + -- a management station). + +snmpInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of Messages delivered to the + SNMP entity from the transport service." + ::= { snmp 1 } + +snmpOutPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + passed from the SNMP protocol entity to the + transport service." + ::= { snmp 2 } + +snmpInBadVersions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + delivered to the SNMP protocol entity and were for + an unsupported SNMP version." + ::= { snmp 3 } + +snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which used a SNMP + community name not known to said entity." + ::= { snmp 4 } + +snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which represented an SNMP + operation which was not allowed by the SNMP + community named in the Message." + ::= { snmp 5 } + +snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ASN.1 or BER errors + encountered by the SNMP protocol entity when + decoding received SNMP Messages." + ::= { snmp 6 } + + -- { snmp 7 } is not used + +snmpInTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `tooBig'." + ::= { snmp 8 } + +snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `noSuchName'." + ::= { snmp 9 } + +snmpInBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 10 } + +snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number valid SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `readOnly'. It should be noted that it is a + protocol error to generate an SNMP PDU which + contains the value `readOnly' in the error-status + field, as such this object is provided as a means + of detecting incorrect implementations of the + SNMP." + ::= { snmp 11 } + +snmpInGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 12 } + +snmpInTotalReqVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + retrieved successfully by the SNMP protocol entity + as the result of receiving valid SNMP Get-Request + and Get-Next PDUs." + ::= { snmp 13 } + +snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + altered successfully by the SNMP protocol entity + as the result of receiving valid SNMP Set-Request + PDUs." + ::= { snmp 14 } + +snmpInGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 15 } + +snmpInGetNexts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 16 } + +snmpInSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 17 } + +snmpInGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 18 } + +snmpInTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 19 } + +snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `tooBig.'" + ::= { snmp 20 } + +snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status is + `noSuchName'." + ::= { snmp 21 } + +snmpOutBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 22 } + + -- { snmp 23 } is not used + +snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 24 } + +snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 25 } + +snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 26 } + +snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 27 } + +snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 28 } + +snmpOutTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 29 } + +snmpEnableAuthenTraps OBJECT-TYPE + SYNTAX INTEGER { enabled(1), disabled(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Indicates whether the SNMP agent process is + permitted to generate authentication-failure + traps. The value of this object overrides any + configuration information; as such, it provides a + means whereby all authentication-failure traps may + be disabled. + + Note that it is strongly recommended that this + object be stored in non-volatile memory so that it + remains constant between re-initializations of the + network management system." + ::= { snmp 30 } + +coldStart TRAP-TYPE + ENTERPRISE snmp + DESCRIPTION + "A coldStart trap signifies that the sending + protocol entity is reinitializing itself such + that the agent's configuration or the rotocol + entity implementation may be altered." + ::= 0 + +warmStart TRAP-TYPE + ENTERPRISE snmp + DESCRIPTION + "A warmStart trap signifies that the sending + protocol entity is reinitializing itself such + that neither the agent configuration nor the + protocol entity implementation is altered." + ::= 1 + +authenticationFailure TRAP-TYPE + ENTERPRISE snmp + DESCRIPTION + "An authenticationFailure trap signifies that + the sending protocol entity is the addressee + of a protocol message that is not properly + authenticated. While implementations of the + SNMP must be capable of generating this trap, + they must also be capable of suppressing the + emission of such traps via an implementation- + specific mechanism." + ::= 4 + +END + diff --git a/lib/snmp/test/snmp_test_data/Test1.funcs b/lib/snmp/test/snmp_test_data/Test1.funcs new file mode 100644 index 0000000000..a9ef7a34fe --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Test1.funcs @@ -0,0 +1,7 @@ +{bits1, {test1, bits1, []}}. +{bits2, {test1, bits2, []}}. +{bits3, {test1, bits3, []}}. +{bits4, {test1, bits4, []}}. +{opaqueObj, {test1, opaque_obj, []}}. +{cnt64, {test1, cnt64, []}}. +{multiStr, {test1, multiStr, []}}. diff --git a/lib/snmp/test/snmp_test_data/Test1.mib b/lib/snmp/test/snmp_test_data/Test1.mib new file mode 100644 index 0000000000..d324b1f1e7 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Test1.mib @@ -0,0 +1,370 @@ +Test1 DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2, enterprises, IpAddress, + Integer32, Counter64, Opaque + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp, RowStatus, TruthValue, + TEXTUAL-CONVENTION + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF + sysLocation, sysContact + FROM SNMPv2-MIB + ; + +snmpMIB MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "" + CONTACT-INFO + "" + DESCRIPTION + "Test mib" + ::= { snmpModules 1 } + + +test OBJECT IDENTIFIER ::= { mib-2 15 } +testTrap OBJECT IDENTIFIER ::= { test 0 } + +bits1 OBJECT-TYPE + SYNTAX BITS { b0(0), b1(1), b2(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test 1 } + +bits2 OBJECT-TYPE + SYNTAX BITS { b0(0), b1(1), b2(2), b3(3), b4(4), b5(5), b6(6), b7(7), + b8(8), b9(9), b10(10), b11(11), b12(12), b13(13), b14(14), b15(15) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test 2 } + +bits3 OBJECT-TYPE + SYNTAX BITS { b0(0), b1(1), b2(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test 3 } + +bits4 OBJECT-TYPE + SYNTAX BITS { b0(0), b1(1), b2(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test 4 } + +testTable OBJECT-TYPE + SYNTAX SEQUENCE OF TestEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Used to test IMPLIED with one string." + ::= { test 5 } + +testEntry OBJECT-TYPE + SYNTAX TestEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { IMPLIED testIndex } + ::= { testTable 1 } + +TestEntry ::= SEQUENCE { + testIndex DisplayString, + testDescr DisplayString, + testStatus RowStatus +} + +testIndex OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { testEntry 1 } + +testDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { testEntry 2 } +testStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row." + ::= { testEntry 3 } + + +testTable2 OBJECT-TYPE + SYNTAX SEQUENCE OF TestEntry2 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Used to test IMPLIED with more than one index." + ::= { test 6 } + +testEntry2 OBJECT-TYPE + SYNTAX TestEntry2 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { testIndex1, IMPLIED testIndex2 } + ::= { testTable2 1 } + +TestEntry2 ::= SEQUENCE { + testIndex1 Integer32, + testIndex2 DisplayString, + testDescr2 DisplayString, + testStatus2 RowStatus +} + +testIndex1 OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { testEntry2 1 } + +testIndex2 OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { testEntry2 2 } + +testDescr2 OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { testEntry2 3 } + +testStatus2 OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row." + ::= { testEntry2 4 } + +sparseTable OBJECT-TYPE + SYNTAX SEQUENCE OF SparseEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Used to test sparse table" + ::= { test 7 } + +sparseEntry OBJECT-TYPE + SYNTAX SparseEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { sparseIndex } + ::= { sparseTable 1 } + +SparseEntry ::= SEQUENCE { + sparseIndex Integer32, + sparseObj DisplayString, + sparseObj2 DisplayString, + sparseDescr DisplayString, + sparseStatus RowStatus +} + +sparseIndex OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { sparseEntry 1 } + +sparseObj OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS not-accessible + STATUS obsolete + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { sparseEntry 2 } + +sparseObj2 OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { sparseEntry 3 } + +sparseDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { sparseEntry 4 } + +sparseStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row." + ::= { sparseEntry 6 } + +sparseStr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + DEFVAL { "slut" } + ::= { test 8 } + +cntTable OBJECT-TYPE + SYNTAX SEQUENCE OF CntEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "" + ::= { test 9 } + +cntEntry OBJECT-TYPE + SYNTAX CntEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { cntIndex } + ::= { cntTable 1 } + +CntEntry ::= SEQUENCE { + cntIndex Integer32, + cntCnt Counter64, + cntStatus RowStatus, + cntDescr DisplayString +} + +cntIndex OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { cntEntry 1 } + +cntCnt OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Counter64 object - not visible in v1" + DEFVAL { 0 } + ::= { cntEntry 5 } + +cntStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this conceptual row." + ::= { cntEntry 7 } + +cntDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + DEFVAL { "descr" } + ::= { cntEntry 8 } + +cntStr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + DEFVAL { "slut" } + ::= { test 10 } + +cnt64 OBJECT-TYPE + SYNTAX Counter64 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "not visible in v1" + ::= { test 11 } + +cnt64Str OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Used to stop get-next from cnt64" + DEFVAL { "after cnt64" } + ::= { test 12 } + +opaqueObj OBJECT-TYPE + SYNTAX Opaque + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { test 13 } + +multiStr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Used to block agent for testing multi threaded impl" + DEFVAL { "no" } + ::= { test 14 } + + +cntTrap NOTIFICATION-TYPE + OBJECTS { sysContact, cnt64, sysLocation } + STATUS current + DESCRIPTION + "Test that coutner64 is deleted from v1 trap" + ::= { testTrap 1 } + +mtTrap NOTIFICATION-TYPE + OBJECTS { multiStr } + STATUS current + DESCRIPTION + "" + ::= { testTrap 2 } + +END diff --git a/lib/snmp/test/snmp_test_data/Test2.funcs b/lib/snmp/test/snmp_test_data/Test2.funcs new file mode 100644 index 0000000000..326ba8405c --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Test2.funcs @@ -0,0 +1,10 @@ +{tDescr2, {test2, tDescr, [2]}}. +{tDescr3, {test2, tDescr, [3]}}. +{tDescr4, {test2, tDescr, [4]}}. +{tInt3, {test2, tInt, [3]}}. +{tTable, {test2, tTable, []}}. +{tTable2, {test2, tTable2, []}}. +{tGenErr1, {test2, tGenErr, [1]}}. +{tGenErr2, {test2, tGenErr, [2]}}. +{tGenErr3, {test2, tGenErr, [3]}}. +{tTooBig, {test2, tTooBig, []}}. diff --git a/lib/snmp/test/snmp_test_data/Test2.mib b/lib/snmp/test/snmp_test_data/Test2.mib new file mode 100644 index 0000000000..81f36175c0 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Test2.mib @@ -0,0 +1,246 @@ +Test2 DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2, enterprises, IpAddress, + Integer32, OBJECT-IDENTITY + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp, RowStatus, TruthValue, + TEXTUAL-CONVENTION + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF; + +snmpMIB MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "" + CONTACT-INFO + "" + DESCRIPTION + "Test mib, used to test processing of requests." + ::= { snmpModules 1 } + + +test2 OBJECT IDENTIFIER ::= { mib-2 16 } +test3 OBJECT IDENTIFIER ::= { mib-2 17 } + +xDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Outside mibview" + ::= { test3 1 } + +xDescr2 OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test3 2 } + + +tDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Outside mibview" + ::= { test2 1 } + +tDescr2 OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test2 2 } + +tDescr3 OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { test2 3 } + +tDescr4 OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "" + ::= { test2 4 } + +tTable OBJECT-TYPE + SYNTAX SEQUENCE OF TEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The (conceptual) table listing the capabilities of the + local SNMPv2 entity acting in an agent role with respect to + various MIB modules. SNMPv2 entities having dynamically- + configurable support of MIB modules will have a + dynamically-varying number of conceptual rows." + ::= { test2 5 } + +tEntry OBJECT-TYPE + SYNTAX TEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { tIndex } + ::= { tTable 1 } + +TEntry ::= SEQUENCE { + tIndex DisplayString, + tDescrX DisplayString, + tCnt Counter32 +} + +tIndex OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { tEntry 1 } + +tDescrX OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { tEntry 2 } + +tCnt OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { tEntry 3 } + +testErr OBJECT-IDENTITY + STATUS current + DESCRIPTION + "" + ::= { test2 6 } + +tTooBig OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "This object will generate a tooBig error" + ::= { testErr 1 } + +tGenErr1 OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This object will generate a genErr error" + ::= { testErr 2 } + +tGenErr2 OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This object will generate a genErr error" + ::= { testErr 3 } + +tGenErr3 OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This object will generate a genErr error" + ::= { testErr 4 } + +tStr OBJECT-TYPE + SYNTAX DisplayString (SIZE (1..4)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test2 7 } + +tInt1 OBJECT-TYPE + SYNTAX INTEGER (1..4) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test2 8 } + +tInt2 OBJECT-TYPE + SYNTAX INTEGER { v1(1), v2(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test2 9 } + +tInt3 OBJECT-TYPE + SYNTAX INTEGER (1..7) -- (1..4 | 6..7) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "" + ::= { test2 10 } + + +tTable2 OBJECT-TYPE + SYNTAX SEQUENCE OF TEntry2 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The (conceptual) table listing the capabilities of the + local SNMPv2 entity acting in an agent role with respect to + various MIB modules. SNMPv2 entities having dynamically- + configurable support of MIB modules will have a + dynamically-varying number of conceptual rows." + ::= { snmpModules 99 } + +tEntry2 OBJECT-TYPE + SYNTAX TEntry2 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { tIndex2 } + ::= { tTable2 1 } + +TEntry2 ::= SEQUENCE { + tIndex2 DisplayString, + tCnt2 Counter32 +} + +tIndex2 OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { tEntry2 1 } + +tCnt2 OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { tEntry2 2 } + + +END diff --git a/lib/snmp/test/snmp_test_data/TestTrap.mib b/lib/snmp/test/snmp_test_data/TestTrap.mib new file mode 100644 index 0000000000..afa97f1188 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/TestTrap.mib @@ -0,0 +1,44 @@ +TestTrap DEFINITIONS ::= BEGIN + + IMPORTS + Counter, TimeTicks, IpAddress + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212 + mgmt, NetworkAddress, IpAddress, Counter, Gauge, + TimeTicks + FROM RFC1155-SMI + DisplayString, snmp, system,sysContact, ifIndex + FROM RFC1213-MIB + OBJECT-TYPE + FROM RFC-1212; + + + + testTrap1 TRAP-TYPE + ENTERPRISE snmp + VARIABLES { sysContact } + DESCRIPTION + "" + ::= 1 + + testTrap2 TRAP-TYPE + ENTERPRISE system + VARIABLES { sysContact } + DESCRIPTION + "" + ::= 1 + + + linkDown TRAP-TYPE + ENTERPRISE snmp + VARIABLES { ifIndex } + DESCRIPTION + "A linkDown trap signifies that the sending + protocol entity recognizes a failure in one of + the communication links represented in the + agent's configuration." + ::= 2 + + +END diff --git a/lib/snmp/test/snmp_test_data/TestTrapv2.mib b/lib/snmp/test/snmp_test_data/TestTrapv2.mib new file mode 100644 index 0000000000..679ddc14b0 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/TestTrapv2.mib @@ -0,0 +1,71 @@ +TestTrapv2 DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2, enterprises, IpAddress, + Integer32 + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp, RowStatus, TruthValue, + TEXTUAL-CONVENTION + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF + + system, snmp, ifIndex, ifAdminStatus, ifOperStatus + FROM RFC1213-MIB + snmpTraps + FROM SNMPv2-MIB; + +testTrapv2 MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "IETF SNMPv2 Working Group" + CONTACT-INFO + " Marshall T. Rose + + Postal: Dover Beach Consulting, Inc. + 420 Whisman Court + Mountain View, CA 94043-2186 + US + + Tel: +1 415 968 1052 + + E-mail: [email protected]" + DESCRIPTION + "The MIB module for SNMPv2 entities." + REVISION "9304010000Z" + DESCRIPTION + "The initial revision of this MIB module was published as + RFC 1450." + ::= { system 100 } + + +tst OBJECT IDENTIFIER ::= { system 0 } + +testTrapv21 NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "This trap is exactly the v2 correspondance of testTrap1 in + TestTrap mib." + ::= { snmp 1 } + +testTrapv22 NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "This trap is exactly the v2 correspondance of testTrap2 in + TestTrap mib." + ::= { system 0 1 } + +linkUp NOTIFICATION-TYPE + OBJECTS { ifIndex, ifAdminStatus, ifOperStatus } + STATUS current + DESCRIPTION + "A linkUp trap signifies that the SNMPv2 entity, + acting in an agent role, has detected that the + ifOperStatus object for one of its communication links + has transitioned out of the down state." + ::= { snmpTraps 4 } + + + + +END diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl new file mode 100644 index 0000000000..2586b66a13 --- /dev/null +++ b/lib/snmp/test/snmp_test_lib.erl @@ -0,0 +1,525 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2002-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_test_lib). + +-include_lib("kernel/include/file.hrl"). + + +-export([hostname/0, hostname/1, localhost/0, os_type/0, sz/1, + display_suite_info/1]). +-export([non_pc_tc_maybe_skip/4, os_based_skip/1]). +-export([replace_config/3, set_config/3, get_config/2, get_config/3]). +-export([fail/3, skip/3]). +-export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]). +-export([flush_mqueue/0, trap_exit/0, trap_exit/1]). +-export([ping/1, local_nodes/0, nodes_on/1]). +-export([start_node/2]). +-export([is_app_running/1, + is_crypto_running/0, is_mnesia_running/0, is_snmp_running/0]). +-export([crypto_start/0, crypto_support/0]). +-export([watchdog/3, watchdog_start/1, watchdog_start/2, watchdog_stop/1]). +-export([del_dir/1]). +-export([cover/1]). +-export([p/2, print/5]). + + +%% ---------------------------------------------------------------------- +%% Misc functions +%% + +hostname() -> + hostname(node()). + +hostname(Node) -> + from($@, atom_to_list(Node)). + +from(H, [H | T]) -> T; +from(H, [_ | T]) -> from(H, T); +from(_H, []) -> []. + +localhost() -> + {ok, Ip} = snmp_misc:ip(net_adm:localhost()), + Ip. + +sz(L) when is_list(L) -> + length(L); +sz(B) when is_binary(B) -> + size(B); +sz(O) -> + {unknown_size,O}. + + +os_type() -> + case (catch test_server:os_type()) of + {'EXIT', _} -> + %% Pre-R10 test server does not have this function + os:type(); + OsType -> + OsType + end. + +display_suite_info(SUITE) when is_atom(SUITE) -> + (catch do_display_suite_info(SUITE)). + +do_display_suite_info(SUITE) -> + MI = SUITE:module_info(), + case (catch display_version(MI)) of + ok -> + ok; + _ -> + case (catch display_app_version(MI)) of + ok -> + ok; + _ -> + io:format("No version info available for test suite ~p~n", + [?MODULE]) + end + end. + +display_version(MI) -> + {value, {compile, CI}} = lists:keysearch(compile, 1, MI), + {value, {options, CO}} = lists:keysearch(options, 1, CI), + Version = version_of_compiler_options(CO), + io:format("~p version info: " + "~n Version: ~p" + "~n", [?MODULE, Version]), + ok. + +version_of_compiler_options([{d, version, Version} | _]) -> + Version; +version_of_compiler_options([_ | T]) -> + version_of_compiler_options(T). + +display_app_version(MI) -> + {value, {attributes, Attrs}} = lists:keysearch(attributes, 1, MI), + {value, {vsn, Vsn}} = lists:keysearch(vsn, 1, Attrs), + {value, {app_vsn, AppVsn}} = lists:keysearch(app_vsn, 1, Attrs), + io:format("~p version info: " + "~n VSN: ~p" + "~n App vsn: ~s" + "~n", [?MODULE, Vsn, AppVsn]), + ok. + + +%% ---------------------------------------------------------------- +%% Conditional skip of testcases +%% + +non_pc_tc_maybe_skip(Config, Condition, File, Line) + when is_list(Config) andalso is_function(Condition) -> + %% Check if we shall skip the skip + case os:getenv("TS_OS_BASED_SKIP") of + "false" -> + ok; + _ -> + case lists:keysearch(ts, 1, Config) of + {value, {ts, snmp}} -> + %% Always run the testcase if we are using our own + %% test-server... + ok; + _ -> + case Condition() of + true -> + skip(non_pc_testcase, File, Line); + false -> + ok + end + end + end. + + +os_based_skip(any) -> + io:format("os_based_skip(any) -> entry" + "~n", []), + true; +os_based_skip(Skippable) when is_list(Skippable) -> + io:format("os_based_skip -> entry with" + "~n Skippable: ~p" + "~n", [Skippable]), + {OsFam, OsName} = + case os:type() of + {_Fam, _Name} = FamAndName -> + FamAndName; + Fam -> + {Fam, undefined} + end, + io:format("os_based_skip -> os-type: " + "~n OsFam: ~p" + "~n OsName: ~p" + "~n", [OsFam, OsName]), + case lists:member(OsFam, Skippable) of + true -> + true; + false -> + case lists:keysearch(OsFam, 1, Skippable) of + {value, {OsFam, OsName}} -> + true; + {value, {OsFam, OsNames}} when is_list(OsNames) -> + lists:member(OsName, OsNames); + _ -> + false + end + end; +os_based_skip(_Crap) -> + io:format("os_based_skip -> entry with" + "~n _Crap: ~p" + "~n", [_Crap]), + false. + + +%% ---------------------------------------------------------------- +%% Test suite utility functions +%% + +replace_config(Key, Config, NewValue) -> + lists:keyreplace(Key, 1, Config, {Key, NewValue}). + +set_config(Key, Def, Config) -> + case get_config(Key, Config) of + undefined -> + [{Key, Def}|Config]; + _ -> + Config + end. + +get_config(Key,C) -> + get_config(Key,C,undefined). + +get_config(Key,C,Default) -> + case lists:keysearch(Key,1,C) of + {value,{Key,Val}} -> + Val; + _ -> + Default + end. + + +fail(Reason, Mod, Line) -> + exit({suite_failed, Reason, Mod, Line}). + +skip(Reason, Module, Line) -> + String = lists:flatten(io_lib:format("Skipping ~p(~p): ~p~n", + [Module, Line, Reason])), + exit({skipped, String}). + + +%% ---------------------------------------------------------------- +%% Time related function +%% + +millis() -> + erlang:now(). + +millis_diff(A,B) -> + T1 = (element(1,A)*1000000) + element(2,A) + (element(3,A)/1000000), + T2 = (element(1,B)*1000000) + element(2,B) + (element(3,B)/1000000), + T1 - T2. + +hours(N) -> trunc(N * 1000 * 60 * 60). +minutes(N) -> trunc(N * 1000 * 60). +seconds(N) -> trunc(N * 1000). + + +sleep(infinity) -> + receive + after infinity -> + ok + end; +sleep(MSecs) -> + receive + after trunc(MSecs) -> + ok + end, + ok. + + +%% ---------------------------------------------------------------- +%% Process utility function +%% + +flush_mqueue() -> + io:format("~p~n", [lists:reverse(flush_mqueue([]))]). + +flush_mqueue(MQ) -> + receive + Any -> + flush_mqueue([Any|MQ]) + after 0 -> + MQ + end. + + +trap_exit() -> + {trap_exit,Flag} = process_info(self(),trap_exit),Flag. + +trap_exit(Flag) -> + process_flag(trap_exit,Flag). + + + +%% ---------------------------------------------------------------- +%% Node utility functions +%% + +ping(N) -> + case net_adm:ping(N) of + pang -> + error; + pong -> + ok + end. + +local_nodes() -> + nodes_on(net_adm:localhost()). + +nodes_on(Host) when is_list(Host) -> + net_adm:world_list([list_to_atom(Host)]). + + +start_node(Name, Args) -> + Opts = [{cleanup,false}, {args,Args}], + test_server:start_node(Name, slave, Opts). + + +%% ---------------------------------------------------------------- +%% Application and Crypto utility functions +%% + +is_app_running(App) when is_atom(App) -> + Apps = application:which_applications(), + lists:keymember(App,1,Apps). + +is_crypto_running() -> + is_app_running(crypto). + +is_mnesia_running() -> + is_app_running(mnesia). + +is_snmp_running() -> + is_app_running(snmp). + +crypto_start() -> + case (catch crypto:start()) of + ok -> + ok; + {error, {already_started,crypto}} -> + ok; + {'EXIT', Reason} -> + {error, {exit, Reason}}; + Else -> + Else + end. + +crypto_support() -> + crypto_support([md5_mac_96, sha_mac_96], []). + +crypto_support([], []) -> + yes; +crypto_support([], Acc) -> + {no, Acc}; +crypto_support([Func|Funcs], Acc) -> + case is_crypto_supported(Func) of + true -> + crypto_support(Funcs, Acc); + false -> + crypto_support(Funcs, [Func|Acc]) + end. + +is_crypto_supported(Func) -> + %% The 'catch' handles the case when 'crypto' is + %% not present in the system (or not started). + case (catch lists:member(Func, crypto:info())) of + true -> true; + _ -> false + end. + + +%% ---------------------------------------------------------------- +%% Watchdog functions +%% + +watchdog_start(Timeout) -> + watchdog_start(unknown, Timeout). + +watchdog_start(Case, Timeout) -> + spawn_link(?MODULE, watchdog, [Case, Timeout, self()]). + +watchdog_stop(Pid) -> + unlink(Pid), + exit(Pid, kill), + ok. + +watchdog(Case, Timeout0, Pid) -> + process_flag(priority, max), + Timeout = timeout(Timeout0), + receive + after Timeout -> + Mon = erlang:monitor(process, Pid), + case erlang:process_info(Pid) of + undefined -> + ok; + ProcInfo -> + Line = + case lists:keysearch(dictionary, 1, ProcInfo) of + {value, {_, Dict}} when is_list(Dict) -> + case lists:keysearch(test_server_loc, 1, Dict) of + {value, {_, {_Mod, L}}} when is_integer(L) -> + L; + _ -> + 0 + end; + _ -> % This borders on paranoia, but... + 0 + end, + Trap = {timetrap_timeout, Timeout, Line}, + exit(Pid, Trap), + receive + {'DOWN', Mon, process, Pid, _} -> + ok + after 10000 -> + warning_msg("Failed stopping " + "test case ~p process ~p " + "[~w] after ~w: killing instead", + [Case, Pid, Line, Timeout]), + exit(Pid, kill) + end + end + end. + +warning_msg(F, A) -> + (catch error_logger:warning_msg(F ++ "~n", A)). + +timeout(T) -> + trunc(timeout(T, os:type())). + +timeout(T, vxworks) -> + 5 * T * timetrap_scale_factor(); +timeout(T, _) -> + T * timetrap_scale_factor(). + +timetrap_scale_factor() -> + case (catch test_server:timetrap_scale_factor()) of + {'EXIT', _} -> + 1; + N -> + N + end. + + +%% ---------------------------------------------------------------------- +%% file & dir functions +%% + +del_dir(Dir) when is_list(Dir) -> + (catch do_del_dir(Dir)). + +do_del_dir(Dir) -> + io:format("delete directory ~s~n", [Dir]), + case file:list_dir(Dir) of + {ok, Files} -> + Files2 = [filename:join(Dir, File) || File <- Files], + del_dir2(Files2), + case file:del_dir(Dir) of + ok -> + io:format("directory ~s deleted~n", [Dir]), + ok; + {error, eexist} = Error1 -> + io:format("directory not empty: ~n", []), + {ok, Files3} = file:list_dir(Dir), + io:format("found additional files: ~n~p~n", + [Files3]), + throw(Error1); + {error, Reason2} = Error2 -> + io:format("failed deleting directory: ~w~n", [Reason2]), + throw(Error2) + end; + Else -> + Else + end. + +del_dir2([]) -> + ok; +del_dir2([File|Files]) -> + del_file_or_dir(File), + del_dir2(Files). + +del_file_or_dir(FileOrDir) -> + case file:read_file_info(FileOrDir) of + {ok, #file_info{type = directory}} -> + do_del_dir(FileOrDir); + {ok, _} -> + io:format(" delete file ~s~n", [FileOrDir]), + case file:delete(FileOrDir) of + ok -> + io:format(" => deleted~n", []), + ok; + {error, Reason} = Error -> + io:format(" => failed - ~w~n", [Reason]), + throw(Error) + end; + + _ -> + ok + end. + + +%% ---------------------------------------------------------------------- +%% cover functions +%% + +cover([Suite, Case] = Args) when is_atom(Suite) andalso is_atom(Case) -> + Mods0 = cover:compile_directory("../src"), + Mods1 = [Mod || {ok, Mod} <- Mods0], + snmp_test_server:t(Args), + Files0 = [cover:analyse_to_file(Mod) || Mod <- Mods1], + [io:format("Cover output: ~s~n", [File]) || {ok, File} <- Files0], + ok. + + +%% ---------------------------------------------------------------------- +%% (debug) Print functions +%% + +p(Mod, Case) when is_atom(Mod) andalso is_atom(Case) -> + case get(test_case) of + undefined -> + put(test_case, Case), + p("~n~n************ ~w:~w ************", [Mod, Case]); + _ -> + ok + end; + +p(F, A) when is_list(F) andalso is_list(A) -> + io:format(user, F ++ "~n", A). + +print(Prefix, Module, Line, Format, Args) -> + io:format("*** [~s] ~s ~p ~p ~p:~p *** " ++ Format ++ "~n", + [format_timestamp(now()), + Prefix, node(), self(), Module, Line|Args]). + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + diff --git a/lib/snmp/test/snmp_test_lib.hrl b/lib/snmp/test/snmp_test_lib.hrl new file mode 100644 index 0000000000..8cc3f75dc5 --- /dev/null +++ b/lib/snmp/test/snmp_test_lib.hrl @@ -0,0 +1,151 @@ +%%<copyright> +%% <year>2002-2008</year> +%% <holder>Ericsson AB, All Rights Reserved</holder> +%%</copyright> +%%<legalnotice> +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% The Initial Developer of the Original Code is Ericsson AB. +%%</legalnotice> +%% +%%---------------------------------------------------------------------- +%% Purpose: Define common macros for testing +%%---------------------------------------------------------------------- + +%% - (some of the) Macros stolen from the test server - + +%% -define(line,put(test_server_loc,{?MODULE,?LINE}),). + + +%% - Misc macros - + +-ifndef(APPLICATION). +-define(APPLICATION, snmp). +-endif. + +-define(SCONF(K,D,C), snmp_test_lib:set_config(K,D,C)). +-define(GCONF(K,C), snmp_test_lib:get_config(K,C)). +-define(RCONF(K,C,V), snmp_test_lib:replace_config(K,C,V)). +-define(HOSTNAME(N), snmp_test_lib:hostname(N)). +-define(LOCALHOST(), snmp_test_lib:localhost()). +-define(SZ(X), snmp_test_lib:sz(X)). +-define(OSTYPE(), snmp_test_lib:os_type()). +-define(DISPLAY_SUITE_INFO(), snmp_test_lib:display_suite_info(?MODULE)). + + +%% - Test case macros - +-define(OS_BASED_SKIP(Skippable), + snmp_test_lib:os_based_skip(Skippable)). +-define(NON_PC_TC_MAYBE_SKIP(Config, Condition), + snmp_test_lib:non_pc_tc_maybe_skip(Config, Condition, ?MODULE, ?LINE)). +-define(SKIP(Reason), snmp_test_lib:skip(Reason, ?MODULE, ?LINE)). +-define(FAIL(Reason), snmp_test_lib:fail(Reason, ?MODULE, ?LINE)). + + +%% - Time macros - + +-ifdef(DONT_USE_TEST_SERVER). +-define(HOURS(N), snmp_test_lib:hours(N)). +-define(MINS(N), snmp_test_lib:minutes(N)). +-define(SECS(N), snmp_test_lib:seconds(N)). +-else. +-define(HOURS(N), test_server:hours(N)). +-define(MINS(N), test_server:minutes(N)). +-define(SECS(N), test_server:seconds(N)). +-endif. + +-ifdef(DONT_USE_TEST_SERVER). +-define(WD_START(T), snmp_test_lib:watchdog_start(T)). +-define(WD_STOP(P), snmp_test_lib:watchdog_stop(P)). +-else. +-define(WD_START(T), test_server:timetrap(T)). +-define(WD_STOP(P), test_server:timetrap_cancel(P)). +-endif. + +-define(SLEEP(MSEC), snmp_test_lib:sleep(MSEC)). +-define(M(), snmp_test_lib:millis()). +-define(MDIFF(A,B), snmp_test_lib:millis_diff(A,B)). + +%% - Process utility macros - + +-define(FLUSH(), snmp_test_lib:flush_mqueue()). +-define(ETRAP_GET(), snmp_test_lib:trap_exit()). +-define(ETRAP_SET(O), snmp_test_lib:trap_exit(O)). + + +%% - Node utility macros - + +-define(PING(N), snmp_test_lib:ping(N)). +-define(LNODES(), snmp_test_lib:local_nodes()). +-define(NODES(H), snmp_test_lib:nodes_on(H)). +-define(START_NODE(N,A), snmp_test_lib:start_node(N,A)). + + +%% - Application and Crypto utility macros - + +-define(IS_APP_RUNNING(A), snmp_test_lib:is_app_running(A)). +-define(IS_SNMP_RUNNING(), snmp_test_lib:is_snmp_running()). +-define(IS_MNESIA_RUNNING(), snmp_test_lib:is_mnesia_running()). +-define(IS_CRYPTO_RUNNING(), snmp_test_lib:is_crypto_running()). +-define(CRYPTO_START(), snmp_test_lib:crypto_start()). +-define(CRYPTO_SUPPORT(), snmp_test_lib:crypto_support()). + + +%% - Dir macros - + +-define(DEL_DIR(D), snmp_test_lib:del_dir(D)). + + +%% - Print macros + +-define(P(C), snmp_test_lib:p(?MODULE, C)). +-define(P1(F), snmp_test_lib:p(F, [])). +-define(P2(F, A), snmp_test_lib:p(F, A)). + +-ifdef(snmp_debug). +-ifndef(snmp_log). +-define(snmp_log,true). +-endif. +-ifndef(snmp_error). +-define(snmp_error,true). +-endif. +-else. +-ifdef(snmp_log). +-ifndef(snmp_error). +-define(snmp_error,true). +-endif. +-endif. +-endif. + +-ifdef(snmp_debug). +-define(DBG(F,A),?PRINT("DBG",F,A)). +-else. +-define(DBG(F,A),ok). +-endif. + +-ifdef(snmp_log). +-define(LOG(F,A),?PRINT("LOG",F,A)). +-else. +-define(LOG(F,A),ok). +-endif. + +-ifdef(snmp_error). +-define(ERR(F,A),?PRINT("ERR",F,A)). +-else. +-define(ERR(F,A),ok). +-endif. + +-define(INF(F,A),?PRINT("INF",F,A)). + +-define(PRINT(P,F,A), + snmp_test_lib:print(P,?MODULE,?LINE,F,A)). + diff --git a/lib/snmp/test/snmp_test_manager.erl b/lib/snmp/test/snmp_test_manager.erl new file mode 100644 index 0000000000..9d9c52ef8d --- /dev/null +++ b/lib/snmp/test/snmp_test_manager.erl @@ -0,0 +1,388 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% This module implements an SNMP manager used in the test suite +%%---------------------------------------------------------------------- +%% + +-module(snmp_test_manager). + +-behaviour(gen_server). +-behaviour(snmpm_user). + + +%% External exports +-export([ + start_link/0, start_link/1, + stop/0, + + sync_get/1, sync_get/2, + sync_get_next/1, sync_get_next/2, + sync_get_bulk/3, + sync_set/1, sync_set/2 + ]). + + +%% Manager callback API: +-export([ + handle_error/3, + handle_agent/4, + handle_pdu/4, + handle_trap/3, + handle_inform/3, + handle_report/3 + ]). + + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + code_change/3, terminate/2]). + +-record(state, {mgr, parent, req, agent_target_name}). + +-define(SERVER, ?MODULE). +-define(USER, ?MODULE). + + +%%%------------------------------------------------------------------- +%%% API +%%%------------------------------------------------------------------- + +start_link() -> + start_link([]). + +start_link(Opts) -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [self(), Opts], []). + +stop() -> + call(stop). + + +sync_get(Oids) -> + sync_get(Oids, fun(X) -> {ok, X} end). + +sync_get(Oids, Verify) when is_list(Oids) and is_function(Verify) -> + Verify(call({sync_get, Oids})). + + +sync_get_next(Oids) -> + sync_get_next(Oids, fun(X) -> {ok, X} end). + +sync_get_next(Oids, Verify) when is_list(Oids) and is_function(Verify) -> + Verify(call({sync_get_next, Oids})). + + +sync_get_bulk(NR, MR, Oids) -> + sync_get_bulk(NR, MR, Oids, fun(X) -> {ok, X} end). + +sync_get_bulk(NR, MR, Oids, Verify) + when is_integer(NR) and is_integer(MR) and + is_list(Oids) and is_function(Verify) -> + Verify(call({sync_get_bulk, NR, MR, Oids})). + + +sync_set(VarsAndVals) -> + sync_set(VarsAndVals, fun(X) -> {ok, X} end). + +sync_set(VarsAndVals, Verify) + when is_list(VarsAndVals) and is_function(Verify) -> + Verify(call({sync_set, VarsAndVals})). + + +%%%------------------------------------------------------------------- +%%% Callback functions from gen_server +%%%------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Func: init/1 +%% Returns: {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%%-------------------------------------------------------------------- +init([Parent, Opts]) -> + process_flag(trap_exit, true), + case (catch do_init(Opts)) of + {ok, State} -> + {ok, State#state{parent = Parent}}; + {error, Reason} -> + {stop, Reason} + end. + +do_init(Opts) -> + {MgrDir, MgrConf, MgrOpts, AgentTargetName, AgentConf} = parse_opts(Opts), + ok = snmp_config:write_manager_config(MgrDir, "", MgrConf), + {ok, Pid} = snmpm:start_link(MgrOpts), + ok = snmpm:register_user(?USER, ?MODULE, self()), + ok = snmpm:register_agent(?USER, AgentTargetName, AgentConf), + {ok, #state{mgr = Pid, agent_target_name = AgentTargetName}}. + + +parse_opts(Opts) -> + %% Manager config (written to the manager.conf file) + %% Addr = get_opt(addr, Opts, ?HOSTNAME()), + Port = get_opt(port, Opts, 5000), + EngineId = get_opt(engine_id, Opts, "mgrEngine"), + MMS = get_opt(max_message_size, Opts, 484), + + MgrConf = [%% {address, Addr}, + {port, Port}, + {engine_id, EngineId}, + {max_message_size, MMS}], + + + %% Manager options + MgrOpts = get_opt(options, Opts), + MgrDir = get_opt(dir, get_opt(config, MgrOpts, [])), + + + %% Retreive the agent configuration + AgentConf = get_opt(agent_config, Opts), + AgentTarget = get_opt(agent_target, Opts), + {MgrDir, MgrConf, MgrOpts, AgentTarget, AgentConf}. + + +get_opt(Key, Opts) -> + case lists:keysearch(Key, 1, Opts) of + {value, {Key, Val}} -> + Val; + false -> + throw({error, {missing_mandatory, Key}}) + end. + +get_opt(Key, Opts, Def) -> + case lists:keysearch(Key, 1, Opts) of + {value, {Key, Val}} -> + Val; + false -> + Def + end. + + +%%-------------------------------------------------------------------- +%% Func: handle_call/3 +%% Returns: {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | (terminate/2 is called) +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_call(stop, _From, S) -> + (catch snmpm:stop()), + {stop, normal, S}; + +handle_call({sync_get, Oids}, _From, + #state{agent_target_name = TargetName} = S) -> + Reply = (catch snmpm:sync_get(?USER, TargetName, Oids)), + {reply, Reply, S}; + +handle_call({sync_get_next, Oids}, _From, + #state{agent_target_name = TargetName} = S) -> + Reply = (catch snmpm:sync_get_next(?USER, TargetName, Oids)), + {reply, Reply, S}; + +handle_call({sync_get_bulk, NR, MR, Oids}, _From, + #state{agent_target_name = TargetName} = S) -> + Reply = (catch snmpm:sync_get_bulk(?USER, TargetName, NR, MR, Oids)), + {reply, Reply, S}; + +handle_call({sync_set, VarsAndVals}, _From, + #state{agent_target_name = TargetName} = S) -> + Reply = (catch snmpm:sync_set(?USER, TargetName, VarsAndVals)), + {reply, Reply, S}; + +handle_call(Req, From, State) -> + error_msg("received unknown request ~n~p~nFrom ~p", [Req, From]), + {reply, {error, unknown_request}, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_cast/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_cast(Msg, State) -> + error_msg("received unknown message ~n~p", [Msg]), + {noreply, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_info/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_info({snmp_error, ReqId, Reason}, + #state{parent = P} = State) -> + info_msg("received snmp error: " + "~n ReqId: ~w" + "~n Reason: ~p", [ReqId, Reason]), + P ! {snmp_error, ReqId, Reason}, + {noreply, State}; + +handle_info({snmp_agent, Addr, Port, Info, Pid}, + #state{parent = P} = State) -> + error_msg("detected new agent: " + "~n Addr: ~w" + "~n Port: ~p" + "~n Info: ~p", [Addr, Port, Info]), + Pid ! {snmp_agent_reply, ignore, self()}, + P ! {snmp_agent, Addr, Port, Info}, + {noreply, State}; + +handle_info({snmp_pdu, TargetName, ReqId, Resp}, + #state{parent = P} = State) -> + info_msg("received snmp pdu: " + "~n TargetName: ~p" + "~n ReqId: ~w" + "~n Resp: ~p", [TargetName, ReqId, Resp]), + P ! {snmp_pdu, TargetName, ReqId, Resp}, + {noreply, State}; + +handle_info({snmp_trap, TargetName, Info, Pid}, + #state{parent = P} = State) -> + info_msg("received snmp trap: " + "~n TargetName: ~p" + "~n Info: ~p", [TargetName, Info]), + Pid ! {snmp_trap_reply, ignore, self()}, + P ! {snmp_trap, TargetName, Info}, + {noreply, State}; + +handle_info({snmp_inform, TargetName, Info, Pid}, + #state{parent = P} = State) -> + info_msg("received snmp inform: " + "~n TargetName: ~p" + "~n Info: ~p", [TargetName, Info]), + Pid ! {snmp_inform_reply, ignore, self()}, + P ! {snmp_inform, TargetName, Info}, + {noreply, State}; + +handle_info({snmp_report, TargetName, Info, Pid}, + #state{parent = P} = State) -> + info_msg("received snmp report: " + "~n TargetName: ~p" + "~n Info: ~p", [TargetName, Info]), + Pid ! {snmp_report_reply, ignore, self()}, + P ! {snmp_report, TargetName, Info}, + {noreply, State}; + +handle_info(Info, State) -> + error_msg("received unknown info: " + "~n Info: ~p", [Info]), + {noreply, State}. + + +%%-------------------------------------------------------------------- +%% Func: terminate/2 +%% Purpose: Shutdown the server +%% Returns: any (ignored by gen_server) +%%-------------------------------------------------------------------- +terminate(_Reason, _State) -> + ok. + + +code_change({down, _Vsn}, State, _Extra) -> + {ok, State}; + +% upgrade +code_change(_Vsn, State, _Extra) -> + {ok, State}. + + +%%%------------------------------------------------------------------- +%%% Internal functions +%%%------------------------------------------------------------------- + + + + +%% -------------------------------------------------------------------------- +%% +%% SNMP manager callback functions +%% +%% -------------------------------------------------------------------------- + +handle_error(ReqId, Reason, Pid) -> + Pid ! {snmp_error, ReqId, Reason}, + ignore. + + +handle_agent(Addr, Port, SnmpInfo, Pid) -> + Pid ! {snmp_agent, Addr, Port, SnmpInfo, self()}, + receive + {snmp_agent_reply, Reply, Pid} -> + Reply + after 10000 -> + ignore + end. + + +handle_pdu(TargetName, ReqId, SnmpResponse, Pid) -> + Pid ! {snmp_pdu, TargetName, ReqId, SnmpResponse}, + ignore. + + +handle_trap(TargetName, SnmpTrapInfo, Pid) -> + Pid ! {snmp_trap, TargetName, SnmpTrapInfo, self()}, + receive + {snmp_trap_reply, Reply, Pid} -> + Reply + after 10000 -> + ignore + end. + + +handle_inform(TargetName, SnmpInfo, Pid) -> + Pid ! {snmp_inform, TargetName, SnmpInfo, self()}, + receive + {snmp_inform_reply, Reply, Pid} -> + Reply + after 10000 -> + ignore + end. + + +handle_report(TargetName, SnmpInfo, Pid) -> + Pid ! {snmp_report, TargetName, SnmpInfo, self()}, + receive + {snmp_report_reply, Reply, Pid} -> + Reply + after 10000 -> + ignore + end. + + +%%---------------------------------------------------------------------- + +call(Req) -> + gen_server:call(?SERVER, Req, infinity). + +% cast(Msg) -> +% gen_server:cast(?SERVER, Msg). + +info_msg(F, A) -> + catch error_logger:info_msg("*** TEST-MANAGER: " ++ F ++ "~n", A). + +error_msg(F, A) -> + catch error_logger:error_msg("*** TEST-MANAGER: " ++ F ++ "~n", A). + + diff --git a/lib/snmp/test/snmp_test_mgr.erl b/lib/snmp/test/snmp_test_mgr.erl new file mode 100644 index 0000000000..085dc8600f --- /dev/null +++ b/lib/snmp/test/snmp_test_mgr.erl @@ -0,0 +1,1139 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmp_test_mgr). + +%%---------------------------------------------------------------------- +%% This module implements a simple SNMP manager for Erlang. +%%---------------------------------------------------------------------- + +%% c(snmp_test_mgr). +%% snmp_test_mgr:start(). +%% snmp_test_mgr:g([[sysContact,0]]). + +%% snmp_test_mgr:start([{engine_id, "mbjk's engine"}, v3, {agent, "clip"}, {mibs, ["../mibs/SNMPv2-MIB"]}]). + +%% snmp_test_mgr:start([{engine_id, "agentEngine"}, {user, "iwl_test"}, {dir, "mgr_conf"}, {sec_level, authPriv}, v3, {agent, "clip"}]). + +%% User interface +-export([start_link/1, start/1, stop/0, + d/0, discovery/0, + g/1, s/1, gn/1, gn/0, r/0, gb/3, rpl/1, + send_bytes/1, + expect/2,expect/3,expect/4,expect/6,get_response/2, + receive_response/0, + purify_oid/1, + oid_to_name/1, name_to_oid/1]). + +%% Internal exports +-export([get_oid_from_varbind/1, + var_and_value_to_varbind/2, flatten_oid/2, make_vb/1]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]). + +-include_lib("snmp/include/snmp_types.hrl"). +-include_lib("snmp/include/STANDARD-MIB.hrl"). + +-record(state,{dbg = true, + quiet, + parent, + timeout = 3500, + print_traps = true, + mini_mib, + packet_server, + last_sent_pdu, + last_received_pdu}). + +-define(SERVER, ?MODULE). +-define(PACK_SERV, snmp_test_mgr_misc). + +start_link(Options) -> + gen_server:start_link({local, ?SERVER}, ?MODULE, {Options, self()}, []). + +start(Options) -> + gen_server:start({local, ?SERVER}, ?MODULE, {Options, self()}, []). + +stop() -> + call(stop). + +d() -> + discovery(). + +discovery() -> + call(discovery). + +g(Oids) -> + cast({get, Oids}). + +%% VarsAndValues is: {PlainOid, o|s|i, Value} (unknown mibs) | {Oid, Value} +s(VarsAndValues) -> + cast({set, VarsAndValues}). + +gn(Oids) when is_list(Oids) -> + cast({get_next, Oids}); +gn(N) when is_integer(N) -> + cast({iter_get_next, N}). +gn() -> + cast(iter_get_next). + +r() -> + cast(resend_pdu). + +gb(NonRepeaters, MaxRepetitions, Oids) -> + cast({bulk, {NonRepeaters, MaxRepetitions, Oids}}). + +rpl(RespPdu) -> + cast({response, RespPdu}). + +send_bytes(Bytes) -> + cast({send_bytes, Bytes}). + +purify_oid(Oid) -> + call({purify_oid, Oid}, 5000). + +oid_to_name(Oid) -> + call({oid_to_name, Oid}, 5000). + +name_to_oid(Name) -> + call({name_to_oid, Name}, 5000). + + +%%---------------------------------------------------------------------- +%% Purpose: For writing test sequences +%% Args: Y=any (varbinds) | trap | timeout | VarBinds | ErrStatus +%% Returns: ok|{error, Id, Reason} +%%---------------------------------------------------------------------- +expect(Id,Y) -> echo_errors(expect_impl(Id,Y)). +expect(Id,v2trap,VBs) -> echo_errors(expect_impl(Id,v2trap,VBs)); +expect(Id,report,VBs) -> echo_errors(expect_impl(Id,report,VBs)); +expect(Id,{inform, Reply},VBs) -> + echo_errors(expect_impl(Id,{inform,Reply},VBs)). +expect(Id,Err,Idx,VBs) -> echo_errors(expect_impl(Id,Err,Idx,VBs)). +expect(Id,trap, Enterp, Generic, Specific, ExpectedVarbinds) -> + echo_errors(expect_impl(Id,trap,Enterp,Generic, + Specific,ExpectedVarbinds)). + +%%----------------------------------------------------------------- +%% Purpose: For writing test sequences +%%----------------------------------------------------------------- +get_response(Id, Vars) -> echo_errors(get_response_impl(Id, Vars)). + +%%---------------------------------------------------------------------- +%% Receives a response from the agent. +%% Returns: a PDU or {error, Reason}. +%% It doesn't receive traps though. +%%---------------------------------------------------------------------- +receive_response() -> + receive_response(get_timeout()). + +receive_response(Timeout) -> + d("await response within ~w ms",[Timeout]), + receive + {snmp_pdu, PDU} when is_record(PDU, pdu) -> + d("received PDU: ~n\t~p",[PDU]), + PDU + after Timeout -> + d("response timeout",[]), + {error, timeout} + end. + + +get_timeout() -> + case get(receive_response_timeout) of + Int when is_integer(Int) and (Int > 0) -> + Int; + _ -> + get_timeout(os:type()) + end. + +get_timeout(vxworks) -> 7000; +get_timeout(_) -> 3500. + +%%---------------------------------------------------------------------- +%% Receives a trap from the agent. +%% Returns: TrapPdu|{error, Reason} +%%---------------------------------------------------------------------- +receive_trap(Timeout) -> + d("await trap within ~w ms",[Timeout]), + receive + {snmp_pdu, PDU} when is_record(PDU, trappdu) -> + d("received trap-PDU: ~n\t~p",[PDU]), + PDU + after Timeout -> + d("trap timeout",[]), + {error, timeout} + end. + +%%---------------------------------------------------------------------- +%% Options: List of +%% {agent_udp, UDPPort}, {agent, Agent} +%% Optional: +%% {community, String ("public" is default}, quiet, +%% {mibs, List of Filenames}, {trap_udp, UDPPort (default 5000)}, +%%---------------------------------------------------------------------- +init({Options, CallerPid}) -> + put(sname, mgr), + put(verbosity, debug), + {A1,A2,A3} = erlang:now(), + random:seed(A1,A2,A3), + case (catch is_options_ok(Options)) of + true -> + put(debug, get_value(debug, Options, false)), + d("init -> (~p) extract options",[self()]), + PacksDbg = get_value(packet_server_debug, Options, false), + io:format("[~w] ~p -> PacksDbg: ~p~n", [?MODULE, self(), PacksDbg]), + RecBufSz = get_value(recbuf, Options, 1024), + io:format("[~w] ~p -> RecBufSz: ~p~n", [?MODULE, self(), RecBufSz]), + Mibs = get_value(mibs, Options, []), + io:format("[~w] ~p -> Mibs: ~p~n", [?MODULE, self(), Mibs]), + Udp = get_value(agent_udp, Options, 4000), + io:format("[~w] ~p -> Udp: ~p~n", [?MODULE, self(), Udp]), + User = get_value(user, Options, "initial"), + io:format("[~w] ~p -> User: ~p~n", [?MODULE, self(), User]), + EngineId = get_value(engine_id, Options, "agentEngine"), + io:format("[~w] ~p -> EngineId: ~p~n", [?MODULE, self(), EngineId]), + CtxEngineId = get_value(context_engine_id, Options, EngineId), + io:format("[~w] ~p -> CtxEngineId: ~p~n", [?MODULE, self(), CtxEngineId]), + TrapUdp = get_value(trap_udp, Options, 5000), + io:format("[~w] ~p -> TrapUdp: ~p~n", [?MODULE, self(), TrapUdp]), + Dir = get_value(dir, Options, "."), + io:format("[~w] ~p -> Dir: ~p~n", [?MODULE, self(), Dir]), + SecLevel = get_value(sec_level, Options, noAuthNoPriv), + io:format("[~w] ~p -> SecLevel: ~p~n", [?MODULE, self(), SecLevel]), + MiniMIB = snmp_mini_mib:create(Mibs), + io:format("[~w] ~p -> MiniMIB: ~p~n", [?MODULE, self(), MiniMIB]), + Version = case lists:member(v2, Options) of + true -> 'version-2'; + false -> + case lists:member(v3, Options) of + true -> 'version-3'; + false -> 'version-1' + end + end, + io:format("[~w] ~p -> Version: ~p~n", [?MODULE, self(), Version]), + Com = case Version of + 'version-3' -> + get_value(context, Options, ""); + _ -> + get_value(community, Options, "public") + end, + io:format("[~w] ~p -> Com: ~p~n", [?MODULE, self(), Com]), + VsnHdrD = + {Com, User, EngineId, CtxEngineId, mk_seclevel(SecLevel)}, + io:format("[~w] ~p -> VsnHdrD: ~p~n", [?MODULE, self(), VsnHdrD]), + AgIp = case snmp_misc:assq(agent, Options) of + {value, Tuple4} when is_tuple(Tuple4) andalso + (size(Tuple4) =:= 4) -> + Tuple4; + {value, Host} when is_list(Host) -> + {ok, Ip} = snmp_misc:ip(Host), + Ip + end, + io:format("[~w] ~p -> AgIp: ~p~n", [?MODULE, self(), AgIp]), + Quiet = lists:member(quiet, Options), + io:format("[~w] ~p -> Quiet: ~p~n", [?MODULE, self(), Quiet]), + PackServ = start_packet_server(Quiet, Options, CallerPid, + AgIp, Udp, TrapUdp, + VsnHdrD, Version, Dir, RecBufSz, + PacksDbg), + d("init -> packet server: ~p",[PackServ]), + State = #state{parent = CallerPid, + quiet = Quiet, + mini_mib = MiniMIB, + packet_server = PackServ}, + d("init -> done",[]), + {ok, State}; + + {error, Reason} -> + {stop,Reason} + end. + +start_packet_server(false, _Options, _CallerPid, AgIp, Udp, TrapUdp, + VsnHdrD, Version, Dir, RecBufSz, PacksDbg) -> + d("start_packet_server -> entry", []), + ?PACK_SERV:start_link_packet({msg, self()}, + AgIp, Udp, TrapUdp, + VsnHdrD, Version, Dir, RecBufSz, + PacksDbg); +start_packet_server(true, Options, CallerPid, AgIp, Udp, TrapUdp, + VsnHdrD, Version, Dir, RecBufSz, PacksDbg) -> + Type = get_value(receive_type, Options, pdu), + d("start_packet_server -> entry with" + "~n CallerPid: ~p" + "~n when" + "~n Type: ~p",[CallerPid, Type]), + ?PACK_SERV:start_link_packet({Type, CallerPid}, + AgIp, Udp, TrapUdp, + VsnHdrD, Version, Dir, RecBufSz, + PacksDbg). + +is_options_ok([{mibs,List}|Opts]) when is_list(List) -> + is_options_ok(Opts); +is_options_ok([quiet|Opts]) -> + is_options_ok(Opts); +is_options_ok([{agent,_}|Opts]) -> + is_options_ok(Opts); +is_options_ok([{agent_udp,Int}|Opts]) when is_integer(Int) -> + is_options_ok(Opts); +is_options_ok([{trap_udp,Int}|Opts]) when is_integer(Int) -> + is_options_ok(Opts); +is_options_ok([{community,List}|Opts]) when is_list(List) -> + is_options_ok(Opts); +is_options_ok([{dir,List}|Opts]) when is_list(List) -> + is_options_ok(Opts); +is_options_ok([{sec_level,noAuthNoPriv}|Opts]) -> + is_options_ok(Opts); +is_options_ok([{sec_level,authNoPriv}|Opts]) -> + is_options_ok(Opts); +is_options_ok([{sec_level,authPriv}|Opts]) -> + is_options_ok(Opts); +is_options_ok([{context,List}|Opts]) when is_list(List) -> + is_options_ok(Opts); +is_options_ok([{user,List}|Opts]) when is_list(List) -> + is_options_ok(Opts); +is_options_ok([{engine_id,List}|Opts]) when is_list(List) -> + is_options_ok(Opts); +is_options_ok([{context_engine_id,List}|Opts]) when is_list(List) -> + is_options_ok(Opts); +is_options_ok([v1|Opts]) -> + is_options_ok(Opts); +is_options_ok([v2|Opts]) -> + is_options_ok(Opts); +is_options_ok([v3|Opts]) -> + is_options_ok(Opts); +is_options_ok([{debug,Bool}|Opts]) -> + case is_bool(Bool) of + ok -> + is_options_ok(Opts); + error -> + {error, {bad_option, debug, Bool}} + end; +is_options_ok([{packet_server_debug,Bool}|Opts]) -> + case is_bool(Bool) of + ok -> + is_options_ok(Opts); + error -> + {error, {bad_option, packet_server_debug, Bool}} + end; +is_options_ok([{recbuf,Sz}|Opts]) when (0 < Sz) and (Sz =< 65535) -> + is_options_ok(Opts); +is_options_ok([InvOpt|_]) -> + {error,{invalid_option,InvOpt}}; +is_options_ok([]) -> true. + +is_bool(true) -> ok; +is_bool(false) -> ok; +is_bool(_) -> error. + +mk_seclevel(noAuthNoPriv) -> 0; +mk_seclevel(authNoPriv) -> 1; +mk_seclevel(authPriv) -> 3. + + +handle_call({purify_oid, Oid}, _From, #state{mini_mib = MiniMib} = State) -> + d("handle_call -> purify_oid for ~p",[Oid]), + Reply = (catch purify_oid(Oid, MiniMib)), + {reply, Reply, State}; + +handle_call({find_pure_oid, XOid}, _From, State) -> + d("handle_call -> find_pure_oid for ~p",[XOid]), + {reply, catch flatten_oid(XOid, State#state.mini_mib), State}; + +handle_call({oid_to_name, Oid}, _From, State) -> + d("handle_call -> oid_to_name for Oid: ~p",[Oid]), + Reply = + case lists:keysearch(Oid, 1, State#state.mini_mib) of + {value, {_Oid, Name, _Type}} -> + {ok, Name}; + false -> + {error, {no_such_oid, Oid}} + end, + {reply, Reply, State}; + +handle_call({name_to_oid, Name}, _From, State) -> + d("handle_call -> name_to_oid for Name: ~p",[Name]), + Reply = + case lists:keysearch(Name, 2, State#state.mini_mib) of + {value, {Oid, _Name, _Type}} -> + {ok, Oid}; + false -> + {error, {no_such_name, Name}} + end, + {reply, Reply, State}; + +handle_call(stop, _From, #state{mini_mib = MiniMIB} = State) -> + d("handle_call -> stop request",[]), + snmp_mini_mib:delete(MiniMIB), + {stop, normal, ok, State#state{mini_mib = undefined}}; + +handle_call(discovery, _From, State) -> + d("handle_call -> discovery",[]), + {Reply, NewState} = execute_discovery(State), + {reply, Reply, NewState}. + + +handle_cast({get, Oids}, State) -> + d("handle_cast -> get request for ~p", [Oids]), + {noreply, execute_request(get, Oids, State)}; + +handle_cast({set, VariablesAndValues}, State) -> + d("handle_cast -> set request for ~p", [VariablesAndValues]), + {noreply, execute_request(set, VariablesAndValues, State)}; + +handle_cast({get_next, Oids}, State) -> + d("handle_cast -> get-next request for ~p", [Oids]), + {noreply, execute_request(get_next, Oids, State)}; + +handle_cast(iter_get_next, State) + when is_record(State#state.last_received_pdu, pdu) -> + d("handle_cast -> iter_get_next request", []), + PrevPDU = State#state.last_received_pdu, + Oids = [get_oid_from_varbind(Vb) || Vb <- PrevPDU#pdu.varbinds], + {noreply, execute_request(get_next, Oids, State)}; + +handle_cast(iter_get_next, State) -> + ?PACK_SERV:error("[Iterated get-next] No Response PDU to " + "start iterating from.", []), + {noreply, State}; + +handle_cast({iter_get_next, N}, State) -> + d("handle_cast -> iter_get_next(~p) request",[N]), + if + is_record(State#state.last_received_pdu, pdu) -> + PDU = get_next_iter_impl(N, State#state.last_received_pdu, + State#state.mini_mib, + State#state.packet_server), + {noreply, State#state{last_received_pdu = PDU}}; + true -> + ?PACK_SERV:error("[Iterated get-next] No Response PDU to " + "start iterating from.", []), + {noreply, State} + end; + +handle_cast(resend_pdu, #state{last_sent_pdu = PDU} = State) -> + d("handle_cast -> resend_pdu request when" + "~n PDU = ~p", [PDU]), + send_pdu(PDU#pdu{request_id = make_request_id()}, + State#state.mini_mib, + State#state.packet_server), + {noreply, State}; + +handle_cast({bulk, Args}, State) -> + d("handle_bulk -> bulk request for ~p", [Args]), + {noreply, execute_request(bulk, Args, State)}; + +handle_cast({response, RespPdu}, State) -> + d("handle_cast -> response request with ~p", [RespPdu]), + ?PACK_SERV:send_pdu(RespPdu, State#state.packet_server), + {noreply, State}; + +handle_cast({send_bytes, Bytes}, State) -> + d("handle_cast -> send-bytes request for ~p bytes", [sizeOf(Bytes)]), + ?PACK_SERV:send_bytes(Bytes, State#state.packet_server), + {noreply, State}; + +handle_cast(Msg, State) -> + d("handle_cast -> unknown message: " + "~n ~p", [Msg]), + {noreply, State}. + + +handle_info({snmp_msg, Msg, Ip, Udp}, State) -> + io:format("* Got PDU: ~s", [?PACK_SERV:format_hdr(Msg)]), + PDU = ?PACK_SERV:get_pdu(Msg), + echo_pdu(PDU, State#state.mini_mib), + case PDU#pdu.type of + 'inform-request' -> + %% Generate a response... + RespPDU = PDU#pdu{type = 'get-response', + error_status = noError, + error_index = 0}, + RespMsg = ?PACK_SERV:set_pdu(Msg, RespPDU), + ?PACK_SERV:send_msg(RespMsg, State#state.packet_server, Ip, Udp); + _Else -> + ok + end, + {noreply, State#state{last_received_pdu = PDU}}; + +handle_info(Info, State) -> + d("handle_info -> unknown info: " + "~n ~p", [Info]), + {noreply, State}. + + +terminate(Reason, State) -> + d("terminate -> with Reason: ~n\t~p",[Reason]), + ?PACK_SERV:stop(State#state.packet_server). + + +%%---------------------------------------------------------------------- +%% Returns: A new State +%%---------------------------------------------------------------------- +execute_discovery(State) -> + Pdu = make_discovery_pdu(), + Reply = ?PACK_SERV:send_discovery_pdu(Pdu, State#state.packet_server), + {Reply, State#state{last_sent_pdu = Pdu}}. + + +execute_request(Operation, Data, State) -> + case (catch make_pdu(Operation, Data, State#state.mini_mib)) of + {error, {Format, Data2}} -> + report_error(State, Format, Data2), + State; + {error, _Reason} -> + State; + PDU when is_record(PDU, pdu) -> + send_pdu(PDU, State#state.mini_mib, State#state.packet_server), + State#state{last_sent_pdu = PDU} + end. + +report_error(#state{quiet = true, parent = Pid}, Format, Args) -> + Reason = lists:flatten(io_lib:format(Format, Args)), + Pid ! {oid_error, Reason}; +report_error(_, Format, Args) -> + ?PACK_SERV:error(Format, Args). + + +get_oid_from_varbind(#varbind{oid = Oid}) -> Oid. + +send_pdu(PDU, _MiniMIB, PackServ) -> + ?PACK_SERV:send_pdu(PDU, PackServ). + +%%---------------------------------------------------------------------- +%% Purpose: Unnesting of oids like [myTable, 3, 4, "hej", 45] to +%% [1,2,3,3,4,104,101,106,45] +%%---------------------------------------------------------------------- + +purify_oid([A|T], MiniMib) when is_atom(A) -> + Oid2 = + case snmp_mini_mib:oid(MiniMib, A) of + false -> + throw({error, {unknown_aliasname, A}}); + Oid -> + lists:flatten([Oid|T]) + end, + {ok, verify_pure_oid(Oid2)}; +purify_oid(L, _) when is_list(L) -> + {ok, verify_pure_oid(lists:flatten(L))}; +purify_oid(X, _) -> + {error, {invalid_oid, X}}. + +verify_pure_oid([]) -> + []; +verify_pure_oid([H | T]) when is_integer(H) and (H >= 0) -> + [H | verify_pure_oid(T)]; +verify_pure_oid([H | _]) -> + throw({error, {not_pure_oid, H}}). + +flatten_oid(XOid, DB) -> + Oid = case XOid of + [A|T] when is_atom(A) -> + [remove_atom(A, DB)|T]; + L when is_list(L) -> + XOid; + Shit -> + throw({error, + {"Invalid oid, not a list of integers: ~w", [Shit]}}) + end, + check_is_pure_oid(lists:flatten(Oid)). + +remove_atom(AliasName, DB) when is_atom(AliasName) -> + case snmp_mini_mib:oid(DB, AliasName) of + false -> + throw({error, {"Unknown aliasname in oid: ~w", [AliasName]}}); + Oid -> + Oid + end; +remove_atom(X, _DB) -> + X. + +%%---------------------------------------------------------------------- +%% Throws if not a list of integers +%%---------------------------------------------------------------------- +check_is_pure_oid([]) -> []; +check_is_pure_oid([X | T]) when is_integer(X) and (X >= 0) -> + [X | check_is_pure_oid(T)]; +check_is_pure_oid([X | _T]) -> + throw({error, {"Invalid oid, it contains a non-integer: ~w", [X]}}). + +get_next_iter_impl(0, PrevPDU, _MiniMIB, _PackServ) -> + PrevPDU; +get_next_iter_impl(N, PrevPDU, MiniMIB, PackServ) -> + Oids = [get_oid_from_varbind(Vb) || Vb <- PrevPDU#pdu.varbinds], + PDU = make_pdu(get_next, Oids, MiniMIB), + send_pdu(PDU, MiniMIB, PackServ), + case receive_response() of + {error, timeout} -> + io:format("(timeout)~n"), + get_next_iter_impl(N, PrevPDU, MiniMIB, PackServ); + {error, _Reason} -> + PrevPDU; + RPDU when is_record(RPDU, pdu) -> + io:format("(~w)", [N]), + echo_pdu(RPDU, MiniMIB), + get_next_iter_impl(N-1, RPDU, MiniMIB, PackServ) + end. + +%%-------------------------------------------------- +%% Used to resend a PDU. Takes the old PDU and +%% generates a fresh one (with a new requestID). +%%-------------------------------------------------- + +make_pdu(set, VarsAndValues, MiniMIB) -> + VBs = [var_and_value_to_varbind(VAV, MiniMIB) || VAV <- VarsAndValues], + make_pdu_impl(set, VBs); +make_pdu(bulk, {NonRepeaters, MaxRepetitions, Oids}, MiniMIB) -> + Foids = [flatten_oid(Oid, MiniMIB) || Oid <- Oids], + #pdu{type = 'get-bulk-request', + request_id = make_request_id(), + error_status = NonRepeaters, + error_index = MaxRepetitions, + varbinds = [make_vb(Oid) || Oid <- Foids]}; +make_pdu(Operation, Oids, MiniMIB) -> + Foids = [flatten_oid(Oid, MiniMIB) || Oid <- Oids], + make_pdu_impl(Operation, Foids). + +make_pdu_impl(get, Oids) -> + #pdu{type = 'get-request', + request_id = make_request_id(), + error_status = noError, + error_index = 0, + varbinds = [make_vb(Oid) || Oid <- Oids]}; + +make_pdu_impl(get_next, Oids) -> + #pdu{type = 'get-next-request', + request_id = make_request_id(), + error_status = noError, + error_index = 0, + varbinds = [make_vb(Oid) || Oid <- Oids]}; + +make_pdu_impl(set, Varbinds) -> + #pdu{type = 'set-request', + request_id = make_request_id(), + error_status = noError, + error_index = 0, + varbinds = Varbinds}. + +make_discovery_pdu() -> + make_pdu_impl(get, []). + +var_and_value_to_varbind({Oid, Type, Value}, MiniMIB) -> + Oid2 = flatten_oid(Oid, MiniMIB), + #varbind{oid = Oid2, + variabletype = char_to_type(Type), + value = Value}; +var_and_value_to_varbind({XOid, Value}, MiniMIB) -> + Oid = flatten_oid(XOid, MiniMIB), + #varbind{oid = Oid, + variabletype = snmp_mini_mib:type(MiniMIB, Oid), + value = Value}. + +char_to_type(o) -> + 'OBJECT IDENTIFIER'; +char_to_type(i) -> + 'INTEGER'; +char_to_type(u) -> + 'Unsigned32'; +char_to_type(g) -> % Gauge, Gauge32 + 'Unsigned32'; +char_to_type(s) -> + 'OCTET STRING'. + +make_vb(Oid) -> + #varbind{oid = Oid, variabletype = 'NULL', value = 'NULL'}. + +make_request_id() -> + random:uniform(16#FFFFFFF-1). + +echo_pdu(PDU, MiniMIB) -> + io:format("~s", [snmp_misc:format_pdu(PDU, MiniMIB)]). + + +%%---------------------------------------------------------------------- +%% Test Sequence +%%---------------------------------------------------------------------- +echo_errors({error, Id, {ExpectedFormat, ExpectedData}, {Format, Data}})-> + io:format("* Unexpected Behaviour * Id: ~w.~n" + " Expected: " ++ ExpectedFormat ++ "~n" + " Got: " ++ Format ++ "~n", + [Id] ++ ExpectedData ++ Data), + {error, Id, {ExpectedFormat, ExpectedData}, {Format, Data}}; +echo_errors(ok) -> ok; +echo_errors({ok, Val}) -> {ok, Val}. + +get_response_impl(Id, Vars) -> + case receive_response() of + #pdu{type = 'get-response', + error_status = noError, + error_index = 0, + varbinds = VBs} -> + match_vars(Id, find_pure_oids2(Vars), VBs, []); + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Index2} -> + {error, + Id, + {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", + ['get-response', noError, 0, ReqId]}, + {"Type: ~w, ErrStat: ~w, Idx: ~w", + [Type2, Err2, Index2]}}; + + {error, Reason} -> + format_reason(Id, Reason) + end. + + + +%%---------------------------------------------------------------------- +%% Returns: ok | {error, Id, {ExpectedFormat, ExpectedData}, {Format, Data}} +%%---------------------------------------------------------------------- +expect_impl(Id, any) -> + io:format("expect_impl(~w, any) -> entry ~n", [Id]), + case receive_response() of + PDU when is_record(PDU, pdu) -> ok; + {error, Reason} -> format_reason(Id, Reason) + end; + +expect_impl(Id, return) -> + io:format("expect_impl(~w, return) -> entry ~n", [Id]), + case receive_response() of + PDU when is_record(PDU, pdu) -> {ok, PDU}; + {error, Reason} -> format_reason(Id, Reason) + end; + +expect_impl(Id, trap) -> + io:format("expect_impl(~w, trap) -> entry ~n", [Id]), + case receive_trap(3500) of + PDU when is_record(PDU, trappdu) -> ok; + {error, Reason} -> format_reason(Id, Reason) + end; + +expect_impl(Id, timeout) -> + io:format("expect_impl(~w, timeout) -> entry ~n", [Id]), + receive + X -> + io:format("expect_impl(~w, timeout) -> " + "received unexpected message: ~n~p~n", [Id, X]), + {error, Id, {"Timeout", []}, {"Message ~w", [X]}} + after 3500 -> + ok + end; + +expect_impl(Id, Err) when is_atom(Err) -> + io:format("expect_impl(~w, ~w) -> entry ~n", [Id, Err]), + case receive_response() of + #pdu{error_status = Err} -> + ok; + + #pdu{request_id = ReqId, + error_status = OtherErr} -> + io:format("expect_impl(~w, ~w) -> " + "received pdu (~w) with unexpected error-status: " + "~n~p~n", [Id, Err, ReqId, OtherErr]), + {error, Id, {"ErrorStatus: ~w, RequestId: ~w", [Err,ReqId]}, + {"ErrorStatus: ~w", [OtherErr]}}; + + {error, Reason} -> + format_reason(Id, Reason) + end; + +expect_impl(Id, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> + io:format("expect_impl(~w) -> entry with" + "~n ExpectedVarbinds: ~p~n", [Id, ExpectedVarbinds]), + case receive_response() of + #pdu{type = 'get-response', + error_status = noError, + error_index = 0, + varbinds = VBs} -> + io:format("expect_impl(~w) -> received pdu with" + "~n VBs: ~p~n", [Id, VBs]), + check_vars(Id, find_pure_oids(ExpectedVarbinds), VBs); + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Index2} -> + io:format("expect_impl(~w) -> received unexpected pdu with" + "~n Type2: ~p" + "~n ReqId: ~p" + "~n Err2: ~p" + "~n Index2: ~p" + "~n", [Id, Type2, ReqId, Err2, Index2]), + {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", + ['get-response', noError, 0, ReqId]}, + {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; + + {error, Reason} -> + format_reason(Id, Reason) + end. + +expect_impl(Id, v2trap, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> + io:format("expect_impl(~w, v2trap) -> entry with" + "~n ExpectedVarbinds: ~p~n", [Id, ExpectedVarbinds]), + case receive_response() of + #pdu{type = 'snmpv2-trap', + error_status = noError, + error_index = 0, + varbinds = VBs} -> + io:format("expect_impl(~w, v2trap) -> received pdu with" + "~n VBs: ~p~n", [Id, VBs]), + check_vars(Id, find_pure_oids(ExpectedVarbinds), VBs); + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Index2} -> + io:format("expect_impl(~w, v2trap) -> received unexpected pdu with" + "~n Type2: ~p" + "~n ReqId: ~p" + "~n Err2: ~p" + "~n Index2: ~p" + "~n", [Id, Type2, ReqId, Err2, Index2]), + {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", + ['snmpv2-trap', noError, 0, ReqId]}, + {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; + + {error, Reason} -> + format_reason(Id, Reason) + end; + +expect_impl(Id, report, ExpectedVarbinds) when is_list(ExpectedVarbinds) -> + io:format("expect_impl(~w, report) -> entry with" + "~n ExpectedVarbinds: ~p~n", [Id, ExpectedVarbinds]), + case receive_response() of + #pdu{type = 'report', + error_status = noError, + error_index = 0, + varbinds = VBs} -> + io:format("expect_impl(~w, report) -> received pdu with" + "~n VBs: ~p~n", [Id, VBs]), + check_vars(Id, find_pure_oids(ExpectedVarbinds), VBs); + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Index2} -> + io:format("expect_impl(~w, report) -> received unexpected pdu with" + "~n Type2: ~p" + "~n ReqId: ~p" + "~n Err2: ~p" + "~n Index2: ~p" + "~n", [Id, Type2, ReqId, Err2, Index2]), + {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", + [report, noError, 0, ReqId]}, + {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; + + {error, Reason} -> + format_reason(Id, Reason) + end; + +expect_impl(Id, {inform, Reply}, ExpectedVarbinds) + when is_list(ExpectedVarbinds) -> + io:format("expect_impl(~w, inform) -> entry with" + "~n Reply: ~p" + "~n ExpectedVarbinds: ~p" + "~n", [Id, Reply, ExpectedVarbinds]), + Resp = receive_response(), + case Resp of + #pdu{type = 'inform-request', + error_status = noError, + error_index = 0, + varbinds = VBs} -> + io:format("expect_impl(~w, inform) -> received pdu with" + "~n VBs: ~p~n", [Id, VBs]), + case check_vars(Id, find_pure_oids(ExpectedVarbinds), VBs) of + ok when (Reply == true) -> + io:format("expect_impl(~w, inform) -> send ok response" + "~n", [Id]), + RespPDU = Resp#pdu{type = 'get-response', + error_status = noError, + error_index = 0}, + ?MODULE:rpl(RespPDU), + ok; + ok when (element(1, Reply) == error) -> + io:format("expect_impl(~w, inform) -> send error response" + "~n", [Id]), + {error, Status, Index} = Reply, + RespPDU = Resp#pdu{type = 'get-response', + error_status = Status, + error_index = Index}, + ?MODULE:rpl(RespPDU), + ok; + ok when (Reply == false) -> + io:format("expect_impl(~w, inform) -> no response sent" + "~n", [Id]), + ok; + Else -> + io:format("expect_impl(~w, inform) -> " + "~n Else: ~p" + "~n", [Id, Else]), + Else + end; + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Index2} -> + io:format("expect_impl(~w, inform) -> received unexpected pdu with" + "~n Type2: ~p" + "~n ReqId: ~p" + "~n Err2: ~p" + "~n Index2: ~p" + "~n", [Id, Type2, ReqId, Err2, Index2]), + {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", + ['inform-request', noError, 0, ReqId]}, + {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; + + {error, Reason} -> + io:format("expect_impl(~w, inform) -> receive failed" + "~n Reason: ~p" + "~n", [Id, Reason]), + format_reason(Id, Reason) + end. + +expect_impl(Id, Err, Index, any) -> + io:format("expect_impl(~w, any) -> entry with" + "~n Err: ~p" + "~n Index: ~p" + "~n", [Id, Err, Index]), + case receive_response() of + #pdu{type = 'get-response', + error_status = Err, + error_index = Index} -> + io:format("expect_impl(~w, any) -> received expected pdu" + "~n", [Id]), + ok; + + #pdu{type = 'get-response', error_status = Err} when (Index == any) -> + io:format("expect_impl(~w, any) -> received expected pdu (any)" + "~n", [Id]), + ok; + + #pdu{type = 'get-response', + request_id = ReqId, + error_status = Err, + error_index = Idx} when is_list(Index) -> + io:format("expect_impl(~w, any) -> received pdu: " + "~n ReqId: ~p" + "~n Err: ~p" + "~n Idx: ~p" + "~n", [Id, ReqId, Err, Idx]), + case lists:member(Idx, Index) of + true -> + ok; + false -> + {error, Id, {"ErrStat: ~w, Idx: ~w, RequestId: ~w", + [Err, Index, ReqId]}, + {"ErrStat: ~w, Idx: ~w", [Err, Idx]}} + end; + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Index2} -> + io:format("expect_impl(~w, any) -> received unexpected pdu: " + "~n Type2: ~p" + "~n ReqId: ~p" + "~n Err2: ~p" + "~n Index2: ~p" + "~n", [Id, Type2, ReqId, Err2, Index2]), + {error, Id, {"Type: ~w, ErrStat: ~w, Idx: ~w, RequestId: ~w", + ['get-response', Err, Index, ReqId]}, + {"Type: ~w, ErrStat: ~w, Idx: ~w", [Type2, Err2, Index2]}}; + + {error, Reason} -> + format_reason(Id, Reason) + end; + +expect_impl(Id, Err, Index, ExpectedVarbinds) -> + io:format("expect_impl(~w) -> entry with" + "~n Err: ~p" + "~n Index: ~p" + "~n ExpectedVarbinds: ~p" + "~n", [Id, Err, Index, ExpectedVarbinds]), + PureVBs = find_pure_oids(ExpectedVarbinds), + case receive_response() of + #pdu{type = 'get-response', + error_status = Err, + error_index = Index, + varbinds = VBs} -> + check_vars(Id, PureVBs, VBs); + + #pdu{type = 'get-response', + error_status = Err, + varbinds = VBs} when (Index == any) -> + check_vars(Id, PureVBs, VBs); + + #pdu{type = 'get-response', + request_id = ReqId, + error_status = Err, + error_index = Idx, + varbinds = VBs} when is_list(Index) -> + case lists:member(Idx, Index) of + true -> + check_vars(Id, PureVBs, VBs); + false -> + {error,Id, + {"ErrStat: ~w, Idx: ~w, Varbinds: ~w, RequestId: ~w", + [Err,Index,PureVBs,ReqId]}, + {"ErrStat: ~w, Idx: ~w, Varbinds: ~w", + [Err,Idx,VBs]}} + end; + + #pdu{type = Type2, + request_id = ReqId, + error_status = Err2, + error_index = Index2, + varbinds = VBs} -> + {error,Id, + {"Type: ~w, ErrStat: ~w, Idx: ~w, Varbinds: ~w, RequestId: ~w", + ['get-response',Err,Index,PureVBs,ReqId]}, + {"Type: ~w, ErrStat: ~w Idx: ~w Varbinds: ~w", + [Type2,Err2,Index2,VBs]}}; + + {error, Reason} -> + format_reason(Id, Reason) + end. + +expect_impl(Id, trap, Enterp, Generic, Specific, ExpectedVarbinds) -> + PureE = find_pure_oid(Enterp), + case receive_trap(3500) of + #trappdu{enterprise = PureE, + generic_trap = Generic, + specific_trap = Specific, + varbinds = VBs} -> + check_vars(Id, find_pure_oids(ExpectedVarbinds), VBs); + + #trappdu{enterprise = Ent2, + generic_trap = G2, + specific_trap = Spec2, + varbinds = VBs} -> + {error, Id, + {"Enterprise: ~w, Generic: ~w, Specific: ~w, Varbinds: ~w", + [PureE, Generic, Specific, ExpectedVarbinds]}, + {"Enterprise: ~w, Generic: ~w, Specific: ~w, Varbinds: ~w", + [Ent2, G2, Spec2, VBs]}}; + + {error, Reason} -> + format_reason(Id, Reason) + end. + +format_reason(Id, Reason) -> + {error, Id, {"?", []}, {"~w", [Reason]}}. + +%%---------------------------------------------------------------------- +%% Args: Id, ExpectedVarbinds, GotVarbinds +%% Returns: ok +%% Fails: if not ok +%%---------------------------------------------------------------------- +check_vars(_Id,[], []) -> + ok; +check_vars(Id,Vars, []) -> + {error, Id, {"More Varbinds (~w)", [Vars]}, {"Too few", []}}; +check_vars(Id,[], Varbinds) -> + {error,Id, {"Fewer Varbinds", []}, {"Too many (~w)", [Varbinds]}}; +check_vars(Id,[{_XOid, any} | Vars], [#varbind{oid = _Oid} |Vbs]) -> + check_vars(Id,Vars, Vbs); +check_vars(Id,[{Oid, Val} | Vars], [#varbind{oid = Oid, value = Val} |Vbs]) -> + check_vars(Id,Vars, Vbs); +check_vars(Id,[{Oid, Val} | _], [#varbind{oid = Oid, value = Val2} |_]) -> + {error, Id, {" Varbind: ~w = ~w", [Oid, Val]}, {"Value: ~w", [Val2]}}; +check_vars(Id,[{Oid, _Val} | _], [#varbind{oid = Oid2, value = _Val2} |_]) -> + {error, Id, {"Oid: ~w", [Oid]}, {"Oid: ~w", [Oid2]}}. + +match_vars(Id, [Oid|T], [#varbind{oid = Oid, value = Value} | Vbs], Res) -> + match_vars(Id, T, Vbs, [Value | Res]); +match_vars(_Id, [], [], Res) -> + {ok, lists:reverse(Res)}; +match_vars(Id, [Oid | _], [#varbind{oid = Oid2}], _Res) -> + {error, Id, {" Oid: ~w", [Oid]}, {"Oid2: ~w", [Oid2]}}; +match_vars(Id, Vars, [], _Res) -> + {error, Id, {"More Varbinds (~w)", [Vars]}, {"Too few", []}}; +match_vars(Id, [], Varbinds, _Res) -> + {error,Id, {"Fewer Varbinds", []}, {"Too many (~w)", [Varbinds]}}. + + + +find_pure_oids([]) -> []; +find_pure_oids([{XOid, Q}|T]) -> + [{find_pure_oid(XOid), Q} | find_pure_oids(T)]. + +find_pure_oids2([]) -> []; +find_pure_oids2([XOid|T]) -> + [find_pure_oid(XOid) | find_pure_oids2(T)]. + + +%%---------------------------------------------------------------------- +%% Returns: Oid +%% Fails: malformed oids +%%---------------------------------------------------------------------- +find_pure_oid(XOid) -> + case gen_server:call(?MODULE, {find_pure_oid, XOid}, infinity) of + {error, {Format, Data}} -> + ok = io:format(Format, Data), + exit(malformed_oid); + Oid when is_list(Oid) -> Oid + end. + +get_value(Opt, Opts, Default) -> + case snmp_misc:assq(Opt,Opts) of + {value, C} -> C; + false -> Default + end. + + +%%---------------------------------------------------------------------- + +call(Req) -> + call(Req, infinity). + +call(Req, To) -> + gen_server:call(?SERVER, Req, To). + +cast(Msg) -> + gen_server:cast(?SERVER, Msg). + + +%%---------------------------------------------------------------------- +%% Debug +%%---------------------------------------------------------------------- + +sizeOf(L) when is_list(L) -> + length(lists:flatten(L)); +sizeOf(B) when is_binary(B) -> + size(B). + +d(F,A) -> d(get(debug),F,A). + +d(true,F,A) -> + io:format("*** [~s] MGR_DBG *** " ++ F ++ "~n", + [format_timestamp(now())|A]); +d(_,_F,_A) -> + ok. + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + diff --git a/lib/snmp/test/snmp_test_mgr_misc.erl b/lib/snmp/test/snmp_test_mgr_misc.erl new file mode 100644 index 0000000000..e6220f9241 --- /dev/null +++ b/lib/snmp/test/snmp_test_mgr_misc.erl @@ -0,0 +1,792 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%% +%% ts:run(snmp, snmp_agent_test, [batch]). +%% +-module(snmp_test_mgr_misc). + +%% API +-export([start_link_packet/8, start_link_packet/9, + stop/1, + send_discovery_pdu/2, + send_pdu/2, send_msg/4, send_bytes/2, + error/2, + get_pdu/1, set_pdu/2, format_hdr/1]). + +%% internal exports +-export([init_packet/10]). + +-define(SNMP_USE_V3, true). +-include_lib("snmp/include/snmp_types.hrl"). + + +%%---------------------------------------------------------------------- +%% The InHandler process will receive messages on the form {snmp_pdu, Pdu}. +%%---------------------------------------------------------------------- +start_link_packet(InHandler, + AgentIp, UdpPort, TrapUdp, + VsnHdr, Version, Dir, BufSz) -> + start_link_packet(InHandler, + AgentIp, UdpPort, TrapUdp, + VsnHdr, Version, Dir, BufSz, + false). + +start_link_packet(InHandler, + AgentIp, UdpPort, TrapUdp, + VsnHdr, Version, Dir, BufSz, + Dbg) when is_integer(UdpPort) -> + Args = [self(), InHandler, + AgentIp, UdpPort, TrapUdp, + VsnHdr, Version, Dir, BufSz, + Dbg], + proc_lib:start_link(?MODULE, init_packet, Args). + +stop(Pid) -> + Pid ! {stop, self()}, + receive + {Pid, stopped} -> ok + end. + + +send_discovery_pdu(Pdu, PacketPid) when is_record(Pdu, pdu) -> + PacketPid ! {send_discovery_pdu, self(), Pdu}, + await_discovery_response_pdu(). + +await_discovery_response_pdu() -> + receive + {discovery_response, Reply} -> + Reply + end. + + +send_pdu(Pdu, PacketPid) when is_record(Pdu, pdu) -> + PacketPid ! {send_pdu, Pdu}. + +send_msg(Msg, PacketPid, Ip, Udp) when is_record(Msg, message) -> + PacketPid ! {send_msg, Msg, Ip, Udp}. + +send_bytes(Bytes, PacketPid) -> + PacketPid ! {send_bytes, Bytes}. + +%%-------------------------------------------------- +%% The SNMP encode/decode process +%%-------------------------------------------------- +init_packet(Parent, SnmpMgr, + AgentIp, UdpPort, TrapUdp, + VsnHdr, Version, Dir, BufSz, DbgOptions) -> + put(sname, mgr_misc), + init_debug(DbgOptions), + {ok, UdpId} = gen_udp:open(TrapUdp, [{recbuf,BufSz},{reuseaddr, true}]), + put(msg_id, 1), + proc_lib:init_ack(Parent, self()), + init_usm(Version, Dir), + packet_loop(SnmpMgr, UdpId, AgentIp, UdpPort, VsnHdr, Version, []). + +init_debug(Dbg) when is_atom(Dbg) -> + put(debug,Dbg), + put(verbosity,silence); + %% put(verbosity,trace); +init_debug(DbgOptions) when is_list(DbgOptions) -> + case lists:keysearch(debug, 1, DbgOptions) of + {value, {_, Dbg}} when is_atom(Dbg) -> + put(debug, Dbg); + _ -> + put(debug, false) + end, + case lists:keysearch(verbosity, 1, DbgOptions) of + {value, {_, Ver}} when is_atom(Ver) -> + put(verbosity, Ver); + _ -> + put(verbosity, silence) + end, + ok. + + +packet_loop(SnmpMgr, UdpId, AgentIp, UdpPort, VsnHdr, Version, MsgData) -> + receive + {send_discovery_pdu, From, Pdu} -> + d("packet_loop -> received send_discovery_pdu with" + "~n From: ~p" + "~n Pdu: ~p", [From, Pdu]), + case mk_discovery_msg(Version, Pdu, VsnHdr, "") of + error -> + ok; + {M, B} when is_list(B) -> + put(discovery, {M, From}), + display_outgoing_message(M), + udp_send(UdpId, AgentIp, UdpPort, B) + end, + packet_loop(SnmpMgr, UdpId, AgentIp, UdpPort, VsnHdr, Version, []); + + {send_pdu, Pdu} -> + d("packet_loop -> received send_pdu with" + "~n Pdu: ~p", [Pdu]), + case mk_msg(Version, Pdu, VsnHdr, MsgData) of + error -> + ok; + B when is_list(B) -> + udp_send(UdpId, AgentIp, UdpPort, B) + end, + packet_loop(SnmpMgr,UdpId,AgentIp,UdpPort,VsnHdr,Version,[]); + + {send_msg, Msg, Ip, Udp} -> + d("packet_loop -> received send_msg with" + "~n Msg: ~p" + "~n Ip: ~p" + "~n Udp: ~p", [Msg,Ip,Udp]), + case catch snmp_pdus:enc_message(Msg) of + {'EXIT', Reason} -> + error("Encoding error:" + "~n Msg: ~w" + "~n Reason: ~w",[Msg, Reason]); + B when is_list(B) -> + udp_send(UdpId, Ip, Udp, B) + end, + packet_loop(SnmpMgr,UdpId,AgentIp,UdpPort,VsnHdr,Version,[]); + {udp, UdpId, Ip, UdpPort, Bytes} -> + d("packet_loop -> received udp with" + "~n UdpId: ~p" + "~n Ip: ~p" + "~n UdpPort: ~p" + "~n sz(Bytes): ~p", [UdpId, Ip, UdpPort, sz(Bytes)]), + MsgData3 = handle_udp_packet(Version, erase(discovery), + UdpId, Ip, UdpPort, Bytes, + SnmpMgr, AgentIp), + packet_loop(SnmpMgr,UdpId,AgentIp,UdpPort,VsnHdr,Version, + MsgData3); + {send_bytes, B} -> + d("packet_loop -> received send_bytes with" + "~n sz(B): ~p", [sz(B)]), + udp_send(UdpId, AgentIp, UdpPort, B), + packet_loop(SnmpMgr,UdpId,AgentIp,UdpPort,VsnHdr,Version,[]); + {stop, Pid} -> + d("packet_loop -> received stop from ~p", [Pid]), + gen_udp:close(UdpId), + Pid ! {self(), stopped}, + exit(normal); + Other -> + d("packet_loop -> received unknown" + "~n ~p", [Other]), + exit({snmp_packet_got_other, Other}) + end. + + +handle_udp_packet(_V, undefined, + UdpId, Ip, UdpPort, + Bytes, SnmpMgr, AgentIp) -> + M = (catch snmp_pdus:dec_message_only(Bytes)), + MsgData3 = + case M of + Message when Message#message.version =:= 'version-3' -> + d("handle_udp_packet -> version 3"), + case catch handle_v3_msg(Bytes, Message) of + {ok, NewData, MsgData2} -> + Msg = Message#message{data = NewData}, + case SnmpMgr of + {pdu, Pid} -> + Pdu = get_pdu(Msg), + d("packet_loop -> " + "send pdu to manager (~w): ~p", [Pid, Pdu]), + Pid ! {snmp_pdu, Pdu}; + {msg, Pid} -> + d("packet_loop -> " + "send msg to manager (~w): ~p", [Pid, Msg]), + Pid ! {snmp_msg, Msg, Ip, UdpPort} + end, + MsgData2; + {error, Reason, B} -> + udp_send(UdpId, AgentIp, UdpPort, B), + error("Decoding error. Auto-sending Report.\n" + "Reason: ~w " + "(UDPport: ~w, Ip: ~w)", + [Reason, UdpPort, Ip]), + []; + {error, Reason} -> + error("Decoding error. " + "Bytes: ~w ~n Reason: ~w " + "(UDPport: ~w, Ip: ~w)", + [Bytes, Reason, UdpPort, Ip]), + [] + end; + Message when is_record(Message, message) -> + %% v1 or v2c + d("handle_udp_packet -> version v1 or v2c"), + case catch snmp_pdus:dec_pdu(Message#message.data) of + Pdu when is_record(Pdu, pdu) -> + case SnmpMgr of + {pdu, Pid} -> + d("handle_udp_packet -> " + "send pdu to manager (~w): ~p", + [Pid, Pdu]), + Pid ! {snmp_pdu, Pdu}; + {msg, Pid} -> + d("handle_udp_packet -> " + "send pdu-msg to manager (~w): ~p", + [Pid, Pdu]), + Msg = Message#message{data = Pdu}, + Pid ! {snmp_msg, Msg, Ip, UdpPort} + end; + Pdu when is_record(Pdu, trappdu) -> + case SnmpMgr of + {pdu, Pid} -> + d("handle_udp_packet -> " + "send trap to manager (~w): ~p", + [Pid, Pdu]), + Pid ! {snmp_pdu, Pdu}; + {msg, Pid} -> + d("handle_udp_packet -> " + "send trap-msg to manager (~w): ~p", + [Pid, Pdu]), + Msg = Message#message{data = Pdu}, + Pid ! {snmp_msg, Msg, Ip, UdpPort} + end; + Reason -> + error("Decoding error. " + "Bytes: ~w ~n Reason: ~w " + "(UDPport: ~w, Ip: ~w)", + [Bytes, Reason, UdpPort, Ip]) + end, + []; + Reason -> + error("Decoding error. Bytes: ~w ~n Reason: ~w " + "(UDPport: ~w, Ip: ~w)", + [Bytes, Reason, UdpPort, Ip]), + [] + end, + MsgData3; +handle_udp_packet(V, {DiscoReqMsg, From}, _UdpId, _Ip, _UdpPort, + Bytes, _, _AgentIp) -> + DiscoRspMsg = (catch snmp_pdus:dec_message(Bytes)), + display_incomming_message(DiscoRspMsg), + _Reply = (catch check_discovery_result(V, DiscoReqMsg, DiscoRspMsg)), + case (catch check_discovery_result(V, DiscoReqMsg, DiscoRspMsg)) of + {ok, AgentEngineID} when is_list(AgentEngineID) -> + %% Ok, step 1 complete, now for step 2 + %% Which we skip for now + OK = {ok, AgentEngineID}, + From ! {discovery_response, OK}, + []; + Error -> + From ! {discovery_response, Error}, + [] + end. + + +%% This function assumes that the agent and the manager (thats us) +%% has the same version. +check_discovery_result('version-3', DiscoReqMsg, DiscoRspMsg) -> + ReqMsgID = getMsgID(DiscoReqMsg), + RspMsgID = getMsgID(DiscoRspMsg), + check_msgID(ReqMsgID, RspMsgID), + ReqRequestId = getRequestId('version-3', DiscoReqMsg), + RspRequestId = getRequestId('version-3', DiscoRspMsg), + check_requestId(ReqRequestId, RspRequestId), + {ok, getMsgAuthEngineID(DiscoRspMsg)}; +check_discovery_result(Version, DiscoReqMsg, DiscoRspMsg) -> + ReqRequestId = getRequestId(Version, DiscoReqMsg), + RspRequestId = getRequestId(Version, DiscoRspMsg), + check_requestId(ReqRequestId, RspRequestId), + {ok, getSysDescr(DiscoRspMsg)}. + +check_msgID(ID, ID) -> + ok; +check_msgID(ReqMsgID, RspMsgID) -> + throw({error, {invalid_msgID, ReqMsgID, RspMsgID}}). + +check_requestId(Id,Id) -> + ok; +check_requestId(ReqRequestId, RspRequestId) -> + throw({error, {invalid_requestId, ReqRequestId, RspRequestId}}). + +getMsgID(M) when is_record(M, message) -> + (M#message.vsn_hdr)#v3_hdr.msgID. + +getRequestId('version-3',M) when is_record(M, message) -> + ((M#message.data)#scopedPdu.data)#pdu.request_id; +getRequestId(_Version,M) when is_record(M, message) -> + (M#message.data)#pdu.request_id; +getRequestId(Version,M) -> + io:format("************* ERROR ****************" + "~n Version: ~w" + "~n M: ~w~n", [Version,M]), + throw({error, {unknown_request_id, Version, M}}). + +getMsgAuthEngineID(M) when is_record(M, message) -> + SecParams1 = (M#message.vsn_hdr)#v3_hdr.msgSecurityParameters, + SecParams2 = snmp_pdus:dec_usm_security_parameters(SecParams1), + SecParams2#usmSecurityParameters.msgAuthoritativeEngineID. + +getSysDescr(M) when is_record(M, message) -> + getSysDescr((M#message.data)#pdu.varbinds); +getSysDescr([]) -> + not_found; +getSysDescr([#varbind{oid = [1,3,6,1,2,1,1,1], value = Value}|_]) -> + Value; +getSysDescr([#varbind{oid = [1,3,6,1,2,1,1,1,0], value = Value}|_]) -> + Value; +getSysDescr([_|T]) -> + getSysDescr(T). + +handle_v3_msg(Packet, #message{vsn_hdr = V3Hdr, data = Data}) -> + d("handle_v3_msg -> entry"), + %% Code copied from snmp_mpd.erl + #v3_hdr{msgID = MsgId, msgFlags = MsgFlags, + msgSecurityModel = MsgSecurityModel, + msgSecurityParameters = SecParams} = V3Hdr, + SecModule = get_security_module(MsgSecurityModel), + d("handle_v3_msg -> SecModule: ~p", [SecModule]), + SecLevel = hd(MsgFlags) band 3, + d("handle_v3_msg -> SecLevel: ~p", [SecLevel]), + IsReportable = snmp_misc:is_reportable(MsgFlags), + SecRes = (catch SecModule:process_incoming_msg(list_to_binary(Packet), + Data,SecParams,SecLevel)), + {_SecEngineID, SecName, ScopedPDUBytes, SecData, _} = + check_sec_module_result(SecRes, V3Hdr, Data, IsReportable), + case (catch snmp_pdus:dec_scoped_pdu(ScopedPDUBytes)) of + ScopedPDU when is_record(ScopedPDU, scopedPdu) -> + {ok, ScopedPDU, {MsgId, SecName, SecData}}; + {'EXIT', Reason} -> + throw({error, Reason}); + Error -> + throw({error, {scoped_pdu_decode_failed, Error}}) + end; +handle_v3_msg(_Packet, BadMessage) -> + throw({error, bad_message, BadMessage}). + +get_security_module(?SEC_USM) -> + snmpa_usm; +get_security_module(SecModel) -> + throw({error, {unknown_sec_model, SecModel}}). + +check_sec_module_result(Res, V3Hdr, Data, IsReportable) -> + d("check_sec_module_result -> entry with" + "~n Res: ~p", [Res]), + case Res of + {ok, X} -> + X; + {error, Reason, []} -> + throw({error, {securityError, Reason}}); + {error, Reason, ErrorInfo} when IsReportable == true -> + #v3_hdr{msgID = MsgID, msgSecurityModel = MsgSecModel} = V3Hdr, + case generate_v3_report_msg(MsgID, MsgSecModel, Data, ErrorInfo) of + error -> + throw({error, {securityError, Reason}}); + Packet -> + throw({error, {securityError, Reason}, Packet}) + end; + {error, Reason, _} -> + throw({error, {securityError, Reason}}); + Else -> + throw({error, {securityError, Else}}) + end. + +generate_v3_report_msg(_MsgID, _MsgSecurityModel, Data, ErrorInfo) -> + d("generate_v3_report_msg -> entry with" + "~n ErrorInfo: ~p", [ErrorInfo]), + {Varbind, SecName, Opts} = ErrorInfo, + ReqId = + if is_record(Data, scopedPdu) -> (Data#scopedPdu.data)#pdu.request_id; + true -> 0 + end, + Pdu = #pdu{type = report, request_id = ReqId, + error_status = noError, error_index = 0, + varbinds = [Varbind]}, + SecLevel = snmp_misc:get_option(securityLevel, Opts, 0), + SnmpEngineID = snmp_framework_mib:get_engine_id(), + ContextEngineID = + snmp_misc:get_option(contextEngineID, Opts, SnmpEngineID), + ContextName = snmp_misc:get_option(contextName, Opts, ""), + mk_msg('version-3', Pdu, {ContextName, SecName, SnmpEngineID, + ContextEngineID, SecLevel}, + undefined). + + +error(Format, Data) -> + io:format("*** Error ***~n"), + ok = io:format(Format, Data), + io:format("~n"). + + +mk_discovery_msg('version-3', Pdu, _VsnHdr, UserName) -> + ScopedPDU = #scopedPdu{contextEngineID = "", + contextName = "", + data = Pdu}, + Bytes = snmp_pdus:enc_scoped_pdu(ScopedPDU), + MsgID = get(msg_id), + put(msg_id, MsgID+1), + UsmSecParams = + #usmSecurityParameters{msgAuthoritativeEngineID = "", + msgAuthoritativeEngineBoots = 0, + msgAuthoritativeEngineTime = 0, + msgUserName = UserName, + msgPrivacyParameters = "", + msgAuthenticationParameters = ""}, + SecBytes = snmp_pdus:enc_usm_security_parameters(UsmSecParams), + PduType = Pdu#pdu.type, + Hdr = #v3_hdr{msgID = MsgID, + msgMaxSize = 1000, + msgFlags = snmp_misc:mk_msg_flags(PduType, 0), + msgSecurityModel = ?SEC_USM, + msgSecurityParameters = SecBytes}, + Msg = #message{version = 'version-3', vsn_hdr = Hdr, data = Bytes}, + case (catch snmp_pdus:enc_message_only(Msg)) of + {'EXIT', Reason} -> + error("Discovery encoding error: " + "~n Pdu: ~w" + "~n Reason: ~w",[Pdu, Reason]), + error; + L when is_list(L) -> + {Msg#message{data = ScopedPDU}, L} + end; +mk_discovery_msg(Version, Pdu, {Com, _, _, _, _}, _UserName) -> + Msg = #message{version = Version, vsn_hdr = Com, data = Pdu}, + case catch snmp_pdus:enc_message(Msg) of + {'EXIT', Reason} -> + error("Discovery encoding error:" + "~n Pdu: ~w" + "~n Reason: ~w",[Pdu, Reason]), + error; + L when is_list(L) -> + {Msg, L} + end. + + +mk_msg('version-3', Pdu, {Context, User, EngineID, CtxEngineId, SecLevel}, + MsgData) -> + d("mk_msg(version-3) -> entry with" + "~n Pdu: ~p" + "~n Context: ~p" + "~n User: ~p" + "~n EngineID: ~p" + "~n CtxEngineID: ~p" + "~n SecLevel: ~p", + [Pdu, Context, User, EngineID, CtxEngineId, SecLevel]), + %% Code copied from snmp_mpd.erl + {MsgId, SecName, SecData} = + if + is_tuple(MsgData) andalso (Pdu#pdu.type =:= 'get-response') -> + MsgData; + true -> + Md = get(msg_id), + put(msg_id, Md + 1), + {Md, User, []} + end, + ScopedPDU = #scopedPdu{contextEngineID = CtxEngineId, + contextName = Context, + data = Pdu}, + ScopedPDUBytes = snmp_pdus:enc_scoped_pdu(ScopedPDU), + + PduType = Pdu#pdu.type, + V3Hdr = #v3_hdr{msgID = MsgId, + msgMaxSize = 1000, + msgFlags = snmp_misc:mk_msg_flags(PduType, SecLevel), + msgSecurityModel = ?SEC_USM}, + Message = #message{version = 'version-3', vsn_hdr = V3Hdr, + data = ScopedPDUBytes}, + SecEngineID = case PduType of + 'get-response' -> snmp_framework_mib:get_engine_id(); + _ -> EngineID + end, + case catch snmpa_usm:generate_outgoing_msg(Message, SecEngineID, + SecName, SecData, SecLevel) of + {'EXIT', Reason} -> + error("version-3 message encoding exit" + "~n Pdu: ~w" + "~n Reason: ~w",[Pdu, Reason]), + error; + {error, Reason} -> + error("version-3 message encoding error" + "~n Pdu: ~w" + "~n Reason: ~w",[Pdu, Reason]), + error; + Packet -> + Packet + end; +mk_msg(Version, Pdu, {Com, _User, _EngineID, _Ctx, _SecLevel}, _SecData) -> + Msg = #message{version = Version, vsn_hdr = Com, data = Pdu}, + case catch snmp_pdus:enc_message(Msg) of + {'EXIT', Reason} -> + error("~w encoding error" + "~n Pdu: ~w" + "~n Reason: ~w",[Version, Pdu, Reason]), + error; + B when is_list(B) -> + B + end. + +format_hdr(#message{version = 'version-3', + vsn_hdr = #v3_hdr{msgID = MsgId}, + data = #scopedPdu{contextName = CName}}) -> + io_lib:format("v3, ContextName = \"~s\" Message ID = ~w\n", + [CName, MsgId]); +format_hdr(#message{version = Vsn, vsn_hdr = Com}) -> + io_lib:format("~w, CommunityName = \"~s\"\n", [vsn(Vsn), Com]). + +vsn('version-1') -> v1; +vsn('version-2') -> v2c. + + +udp_send(UdpId, AgentIp, UdpPort, B) -> + case (catch gen_udp:send(UdpId, AgentIp, UdpPort, B)) of + {error,ErrorReason} -> + error("failed (error) sending message to ~p:~p: " + "~n ~p",[AgentIp, UdpPort, ErrorReason]); + {'EXIT',ExitReason} -> + error("failed (exit) sending message to ~p:~p:" + "~n ~p",[AgentIp, UdpPort, ExitReason]); + _ -> + ok + end. + + +get_pdu(#message{version = 'version-3', data = #scopedPdu{data = Pdu}}) -> + Pdu; +get_pdu(#message{data = Pdu}) -> + Pdu. + +set_pdu(Msg, RePdu) when Msg#message.version == 'version-3' -> + SP = (Msg#message.data)#scopedPdu{data = RePdu}, + Msg#message{data = SP}; +set_pdu(Msg, RePdu) -> + Msg#message{data = RePdu}. + + +init_usm('version-3', Dir) -> + ets:new(snmp_agent_table, [set, public, named_table]), + ets:insert(snmp_agent_table, {agent_mib_storage, persistent}), + snmpa_local_db:start_link(normal, Dir, [{verbosity,trace}]), + NameDb = snmpa_agent:db(snmpEngineID), + R = snmp_generic:variable_set(NameDb, "mgrEngine"), + io:format("~w:init_usm -> engine-id set result: ~p~n", [?MODULE,R]), + snmp_framework_mib:set_engine_boots(1), + snmp_framework_mib:set_engine_time(1), + snmp_user_based_sm_mib:reconfigure(Dir); +init_usm(_Vsn, _Dir) -> + ok. + + +display_incomming_message(M) -> + display_message("Incomming",M). + +display_outgoing_message(M) -> + display_message("Outgoing", M). + +display_message(Direction, M) when is_record(M, message) -> + io:format("~s SNMP message:~n", [Direction]), + V = M#message.version, + display_version(V), + display_hdr(V, M#message.vsn_hdr), + display_msg_data(V, Direction, M#message.data); +display_message(Direction, M) -> + io:format("~s message unknown: ~n~p", [Direction, M]). + +display_version('version-3') -> + display_prop("Version",'SNMPv3'); +display_version(V) -> + display_prop("Version",V). + +display_hdr('version-3',H) -> + display_msgID(H#v3_hdr.msgID), + display_msgMaxSize(H#v3_hdr.msgMaxSize), + display_msgFlags(H#v3_hdr.msgFlags), + SecModel = H#v3_hdr.msgSecurityModel, + display_msgSecurityModel(SecModel), + display_msgSecurityParameters(SecModel,H#v3_hdr.msgSecurityParameters); +display_hdr(_V,Community) -> + display_community(Community). + +display_community(Community) -> + display_prop("Community",Community). + +display_msgID(Id) -> + display_prop("msgID",Id). + +display_msgMaxSize(Size) -> + display_prop("msgMaxSize",Size). + +display_msgFlags([Flags]) -> + display_prop("msgFlags",Flags); +display_msgFlags([]) -> + display_prop("msgFlags",no_value_to_display); +display_msgFlags(Flags) -> + display_prop("msgFlags",Flags). + +display_msgSecurityModel(?SEC_USM) -> + display_prop("msgSecurityModel",'USM'); +display_msgSecurityModel(Model) -> + display_prop("msgSecurityModel",Model). + +display_msgSecurityParameters(?SEC_USM,Params) -> + display_usmSecurityParameters(Params); +display_msgSecurityParameters(_Model,Params) -> + display_prop("msgSecurityParameters",Params). + +display_usmSecurityParameters(P) when is_list(P) -> + P1 = lists:flatten(P), + display_usmSecurityParameters(snmp_pdus:dec_usm_security_parameters(P1)); +display_usmSecurityParameters(P) when is_record(P,usmSecurityParameters) -> + ID = P#usmSecurityParameters.msgAuthoritativeEngineID, + display_msgAuthoritativeEngineID(ID), + Boots = P#usmSecurityParameters.msgAuthoritativeEngineBoots, + display_msgAuthoritativeEngineBoots(Boots), + Time = P#usmSecurityParameters.msgAuthoritativeEngineTime, + display_msgAuthoritativeEngineTime(Time), + Name = P#usmSecurityParameters.msgUserName, + display_msgUserName(Name), + SecParams = P#usmSecurityParameters.msgAuthenticationParameters, + display_msgAuthenticationParameters(SecParams), + PrivParams = P#usmSecurityParameters.msgPrivacyParameters, + display_msgPrivacyParameters(PrivParams); +display_usmSecurityParameters(P) -> + display_prop("unknown USM sec paraams",P). + +display_msgAuthoritativeEngineID(ID) -> + display_prop("msgAuthoritativeEngineID",ID). + +display_msgAuthoritativeEngineBoots(V) -> + display_prop("msgAuthoritativeEngineBoots",V). + +display_msgAuthoritativeEngineTime(V) -> + display_prop("msgAuthoritativeEngineTime",V). + +display_msgUserName(V) -> + display_prop("msgUserName",V). + +display_msgAuthenticationParameters(V) -> + display_prop("msgAuthenticationParameters",V). + +display_msgPrivacyParameters(V) -> + display_prop("msgPrivacyParameters",V). + +display_msg_data('version-3',Direction,D) when is_record(D,scopedPdu) -> + display_scoped_pdu(Direction,D); +display_msg_data(_Version,Direction,D) when is_record(D,pdu) -> + display_pdu(Direction,D); +display_msg_data(_Version,_Direction,D) -> + display_prop("Unknown message data",D). + +display_scoped_pdu(Direction,P) -> + display_contextEngineID(P#scopedPdu.contextEngineID), + display_contextName(P#scopedPdu.contextName), + display_scoped_pdu_data(Direction,P#scopedPdu.data). + +display_contextEngineID(Id) -> + display_prop("contextEngineID",Id). + +display_contextName(Name) -> + display_prop("contextName",Name). + +display_scoped_pdu_data(Direction,D) when is_record(D,pdu) -> + display_pdu(Direction,D); +display_scoped_pdu_data(Direction,D) when is_record(D,trappdu) -> + display_trappdu(Direction,D); +display_scoped_pdu_data(_Direction,D) -> + display_prop("Unknown scoped pdu data",D). + +display_pdu(Direction, P) -> + io:format("~s PDU:~n", [Direction]), + display_type(P#pdu.type), + display_request_id(P#pdu.request_id), + display_error_status(P#pdu.error_status), + display_error_index(P#pdu.error_index), + display_varbinds(P#pdu.varbinds). + +display_type(T) -> + display_prop("Type",T). + +display_request_id(Id) -> + display_prop("Request id",Id). + +display_error_status(S) -> + display_prop("Error status",S). + +display_error_index(I) -> + display_prop("Error index",I). + +display_varbinds([H|T]) -> + display_prop_hdr("Varbinds"), + display_varbind(H), + display_varbinds(T); +display_varbinds([]) -> + ok. + +display_varbind(V) when is_record(V,varbind) -> + display_oid(V#varbind.oid), + display_vtype(V#varbind.variabletype), + display_value(V#varbind.value), + display_org_index(V#varbind.org_index); +display_varbind(V) -> + display_prop("\tVarbind",V). + +display_oid(V) -> + display_prop("\tOid",V). + +display_vtype(V) -> + display_prop("\t\tVariable type",V). + +display_value(V) -> + display_prop("\t\tValue",V). + +display_org_index(V) -> + display_prop("\t\tOrg index",V). + +display_trappdu(Direction,P) -> + io:format("~s TRAP-PDU:~n",[Direction]), + display_prop("TRAP-PDU",P). + +display_prop(S,no_value_to_display) -> + io:format("\t~s: ~n",[S]); +display_prop(S,V) -> + io:format("\t~s: ~p~n",[S,V]). + + +display_prop_hdr(S) -> + io:format("\t~s:~n",[S]). + + +%%---------------------------------------------------------------------- +%% Debug +%%---------------------------------------------------------------------- + +sz(L) when is_list(L) -> + length(lists:flatten(L)); +sz(B) when is_binary(B) -> + size(B); +sz(O) -> + {unknown_size, O}. + +d(F) -> d(F, []). +d(F,A) -> d(get(debug),F,A). + +d(true,F,A) -> + io:format("*** [~s] MGR_PS_DBG *** " ++ F ++ "~n", + [format_timestamp(now())|A]); +d(_,_F,_A) -> + ok. + +format_timestamp({_N1, _N2, N3} = Now) -> + {Date, Time} = calendar:now_to_datetime(Now), + {YYYY,MM,DD} = Date, + {Hour,Min,Sec} = Time, + FormatDate = + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), + lists:flatten(FormatDate). + diff --git a/lib/snmp/test/snmp_test_server.erl b/lib/snmp/test/snmp_test_server.erl new file mode 100644 index 0000000000..d0a5185452 --- /dev/null +++ b/lib/snmp/test/snmp_test_server.erl @@ -0,0 +1,416 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2003-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Lightweight test server +%%---------------------------------------------------------------------- + +-module(snmp_test_server). + +-compile(export_all). + +-export([ + run/1, run/2, + + error/3, + skip/3, + fatal_skip/3, + + init_per_testcase/2, + fin_per_testcase/2 + ]). + +-include("snmp_test_lib.hrl"). + +-define(GLOBAL_LOGGER, snmp_global_logger). +-define(TEST_CASE_SUP, snmp_test_case_supervisor). + +-define(d(F,A),d(F,A,?LINE)). + +-ifndef(snmp_priv_dir). +-define(snmp_priv_dir, "run-" ++ timestamp()). +-endif. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Evaluates a test case or test suite +%% Returns a list of failing test cases: +%% +%% {Mod, Fun, ExpectedRes, ActualRes} +%%---------------------------------------------------------------------- + +run([Mod, Fun]) when is_atom(Mod) andalso is_atom(Fun) -> + Res = run({Mod, Fun}, default_config(Mod)), + display_result(Res), + Res; +run({Mod, _Fun} = Case) when is_atom(Mod) -> + io:format("~n", []), + Res = run(Case, default_config(Mod)), + display_result(Res), + Res; +run(Mod) when is_atom(Mod) -> + io:format("~n", []), + Res = run(Mod, default_config(Mod)), + display_result(Res), + Res; +run([Mod]) when is_atom(Mod) -> + io:format("~n", []), + Res = run(Mod, default_config(Mod)), + display_result(Res), + Res. + + +run({Mod, Fun}, Config) when is_atom(Mod) andalso + is_atom(Fun) andalso + is_list(Config) -> + ?d("run(~p,~p) -> entry", [Mod, Fun]), + case (catch apply(Mod, Fun, [suite])) of + [] -> + io:format("~n~n*** Eval: ~p ***************~n", + [{Mod, Fun}]), + case eval(Mod, Fun, Config) of + {ok, _, _} -> + []; + Other -> + [Other] + end; + + Cases when is_list(Cases) -> + io:format("~n*** Expand: ~p ...~n", [{Mod, Fun}]), + Map = fun(Case) when is_atom(Case) -> {Mod, Case}; + (Case) -> Case + end, + run(lists:map(Map, Cases), Config); + + {conf, InitSuite, Cases, FinishSuite} when is_atom(InitSuite) andalso + is_list(Cases) andalso + is_atom(FinishSuite) -> + ?d("run -> conf: " + "~n InitSuite: ~p" + "~n Cases: ~p" + "~n FinishSuite: ~p", [InitSuite, Cases, FinishSuite]), + do_suite(Mod, InitSuite, Cases, FinishSuite, Config); + + {req, _, SubCases} when is_list(SubCases) -> + ?d("run -> req: " + "~n SubCases: ~p", [SubCases]), + do_subcases(Mod, Fun, SubCases, Config, []); + + {req, _, Conf} -> + ?d("run -> req: " + "~n Conf: ~p", [Conf]), + do_subcases(Mod, Fun, [Conf], Config, []); + + {'EXIT', {undef, _}} -> + io:format("~n*** Undefined: ~p~n", [{Mod, Fun}]), + [{nyi, {Mod, Fun}, ok}]; + + Error -> + io:format("~n*** Ignoring: ~p: ~p~n", [{Mod, Fun}, Error]), + [{failed, {Mod, Fun}, Error}] + end; + +run(Mod, Config) when is_atom(Mod) andalso is_list(Config) -> + run({Mod, all}, Config); + +run(Cases, Config) when is_list(Cases) andalso is_list(Config) -> + Errors = [run(Case, Config) || Case <- Cases], + lists:append(Errors); + +run(Bad, _Config) -> + [{badarg, Bad, ok}]. + + +do_suite(Mod, Init, Cases, Finish, Config0) -> + ?d("do_suite -> entry with" + "~n Mod: ~p" + "~n Init: ~p" + "~n Cases: ~p" + "~n Finish: ~p" + "~n Config0: ~p", [Mod, Init, Cases, Finish, Config0]), + case (catch apply(Mod, Init, [Config0])) of + Config when is_list(Config) -> + io:format("~n*** Expand: ~p ...~n", [Mod]), + Map = fun(Case) when is_atom(Case) -> {Mod, Case}; + (Case) -> Case + end, + Res = run(lists:map(Map, Cases), Config), + (catch apply(Mod, Finish, [Config])), + Res; + + {'EXIT', {skipped, Reason}} -> + io:format(" => skipping: ~p~n", [Reason]), + SkippedCases = + [{skipped, {Mod, Case}, suite_init_skipped} || Case <- Cases], + lists:flatten([[{skipped, {Mod, Init}, Reason}], + SkippedCases, + [{skipped, {Mod, Finish}, suite_init_skipped}]]); + + Error -> + io:format(" => init (~p) failed: ~n~p~n", [Init, Error]), + InitResult = + [{failed, {Mod, Init}, Error}], + SkippedCases = + [{skipped, {Mod, Case}, suite_init_failed} || Case <- Cases], + FinResult = + case (catch apply(Mod, Finish, [Config0])) of + ok -> + []; + FinConfig when is_list(FinConfig) -> + []; + FinError -> + [{failed, {Mod, Finish}, FinError}] + end, + lists:flatten([InitResult, SkippedCases, FinResult]) + + end. + + +do_subcases(_Mod, _Fun, [], _Config, Acc) -> + lists:flatten(lists:reverse(Acc)); +do_subcases(Mod, Fun, [{conf, Init, Cases, Finish}|SubCases], Config, Acc) + when is_atom(Init) andalso is_list(Cases) andalso is_atom(Finish) -> + R = case (catch apply(Mod, Init, [Config])) of + Conf when is_list(Conf) -> + io:format("~n*** Expand: ~p ...~n", [{Mod, Fun}]), + Map = fun(Case) when is_atom(Case) -> {Mod, Case}; + (Case) -> Case + end, + Res = run(lists:map(Map, Cases), Conf), + (catch apply(Mod, Finish, [Conf])), + Res; + + {'EXIT', {skipped, Reason}} -> + io:format(" => skipping: ~p~n", [Reason]), + [{skipped, {Mod, Fun}, Reason}]; + + Error -> + io:format(" => init (~p) failed: ~n~p~n", [Init, Error]), + (catch apply(Mod, Finish, [Config])), + [{failed, {Mod, Fun}, Error}] + end, + do_subcases(Mod, Fun, SubCases, Config, [R|Acc]); +do_subcases(Mod, Fun, [SubCase|SubCases], Config, Acc) when atom(SubCase) -> + R = do_case(Mod, SubCase, Config), + do_subcases(Mod, Fun, SubCases,Config, [R|Acc]). + + +do_case(M, F, C) -> + io:format("~n~n*** Eval: ~p ***************~n", [{M, F}]), + case eval(M, F, C) of + {ok, _, _} -> + []; + Other -> + [Other] + end. + + +eval(Mod, Fun, Config) -> + Flag = process_flag(trap_exit, true), + global:register_name(?TEST_CASE_SUP, self()), + Config2 = Mod:init_per_testcase(Fun, Config), + Self = self(), + Eval = fun() -> do_eval(Self, Mod, Fun, Config2) end, + Pid = spawn_link(Eval), + R = wait_for_evaluator(Pid, Mod, Fun, Config2, []), + Mod:fin_per_testcase(Fun, Config2), + global:unregister_name(?TEST_CASE_SUP), + process_flag(trap_exit, Flag), + R. + +wait_for_evaluator(Pid, Mod, Fun, Config, Errors) -> + Pre = lists:concat(["TEST CASE: ", Fun]), + receive + {'EXIT', _Watchdog, watchdog_timeout} -> + io:format("*** ~s WATCHDOG TIMEOUT~n", [Pre]), + exit(Pid, kill), + {failed, {Mod, Fun}, watchdog_timeout}; + {done, Pid, ok} when Errors =:= [] -> + io:format("*** ~s OK~n", [Pre]), + {ok, {Mod, Fun}, Errors}; + {done, Pid, {ok, _}} when Errors =:= [] -> + io:format("*** ~s OK~n", [Pre]), + {ok, {Mod, Fun}, Errors}; + {done, Pid, Fail} -> + io:format("*** ~s FAILED~n~p~n", [Pre, Fail]), + {failed, {Mod, Fun}, Fail}; + {'EXIT', Pid, {skipped, Reason}} -> + io:format("*** ~s SKIPPED~n~p~n", [Pre, Reason]), + {skipped, {Mod, Fun}, Errors}; + {'EXIT', Pid, Reason} -> + io:format("*** ~s CRASHED~n~p~n", [Pre, Reason]), + {crashed, {Mod, Fun}, [{'EXIT', Reason} | Errors]}; + {fail, Pid, Reason} -> + io:format("*** ~s FAILED~n~p~n", [Pre, Reason]), + wait_for_evaluator(Pid, Mod, Fun, Config, Errors ++ [Reason]) + end. + +do_eval(ReplyTo, Mod, Fun, Config) -> + case (catch apply(Mod, Fun, [Config])) of + {'EXIT', {skipped, Reason}} -> + ReplyTo ! {'EXIT', self(), {skipped, Reason}}; + Other -> + ReplyTo ! {done, self(), Other} + end, + unlink(ReplyTo), + exit(shutdown). + + +display_result([]) -> + io:format("TEST OK~n", []); + +display_result(Errors) when is_list(Errors) -> + Nyi = [MF || {nyi, MF, _} <- Errors], + Skipped = [{MF, Reason} || {skipped, MF, Reason} <- Errors], + Crashed = [{MF, Reason} || {crashed, MF, Reason} <- Errors], + Failed = [{MF, Reason} || {failed, MF, Reason} <- Errors], + display_skipped(Skipped), + display_crashed(Crashed), + display_failed(Failed), + display_summery(Nyi, Skipped, Crashed, Failed). + +display_summery(Nyi, Skipped, Crashed, Failed) -> + io:format("~nTest case summery:~n", []), + display_summery(Nyi, "not yet implemented"), + display_summery(Skipped, "skipped"), + display_summery(Crashed, "crashed"), + display_summery(Failed, "failed"), + io:format("~n", []). + +display_summery([], _) -> + ok; +display_summery(Res, Info) -> + io:format(" ~w test cases ~s~n", [length(Res), Info]). + +display_skipped([]) -> + io:format("Skipped test cases: -~n", []); +display_skipped(Skipped) -> + io:format("Skipped test cases:~n", []), + [io:format(" ~p => ~p~n", [MF, Reason]) || {MF, Reason} <- Skipped], + io:format("~n", []). + +display_crashed([]) -> + io:format("Crashed test cases: -~n", []); +display_crashed(Crashed) -> + io:format("Crashed test cases:~n", []), + [io:format(" ~p => ~p~n", [MF, Reason]) || {MF, Reason} <- Crashed], + io:format("~n", []). + +display_failed([]) -> + io:format("Failed test cases: -~n", []); +display_failed(Failed) -> + io:format("Failed test cases:~n", []), + [io:format(" ~p => ~p~n", [MF, Reason]) || {MF, Reason} <- Failed], + io:format("~n", []). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Verify that the actual result of a test case matches the exected one +%% Returns the actual result +%% Stores the result in the process dictionary if mismatch + +error(Actual, Mod, Line) -> + global:send(?GLOBAL_LOGGER, {failed, Mod, Line}), + log("<ERROR> Bad result: ~p~n", [Actual], Mod, Line), + case global:whereis_name(?TEST_CASE_SUP) of + undefined -> + ignore; + Pid -> + Pid ! {fail, self(), {Actual, Mod, Line}} + end, + Actual. + +skip(Actual, Mod, Line) -> + log("Skipping test case~n", [], Mod, Line), + exit({skipped, {Actual, Mod, Line}}). + +fatal_skip(Actual, Mod, Line) -> + error(Actual, Mod, Line), + exit(shutdown). + + +log(Format, Args, Mod, Line) -> + case global:whereis_name(?GLOBAL_LOGGER) of + undefined -> + io:format(user, "~p(~p): " ++ Format, [Mod, Line] ++ Args); + Pid -> + io:format(Pid, "~p(~p): " ++ Format, [Mod, Line] ++ Args) + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Test server callbacks + +init_per_testcase(_Case, Config) -> + global:register_name(?GLOBAL_LOGGER, group_leader()), + Config. + +fin_per_testcase(_Case, _Config) -> + global:unregister_name(?GLOBAL_LOGGER), + ok. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Internal utility functions + +default_config(Mod) -> + PrivDir0 = ?snmp_priv_dir, + case filename:pathtype(PrivDir0) of + absolute -> + ok; + _ -> + case file:make_dir(Mod) of + ok -> + ok; + {error, eexist} -> + ok + end, + PrivDir = filename:join(Mod, PrivDir0), + case file:make_dir(PrivDir) of + ok -> + ok; + {error, eexist} -> + ok; + Error -> + ?FAIL({failed_creating_subsuite_top_dir, Error}) + end, + [{priv_dir, PrivDir}] + end. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +d(F, A, L) -> + d(true, F, A, L). + %% d(get(dbg), F, A, L). + +d(true, F, A, L) -> + io:format("STS[~w] ~p " ++ F ++ "~n", [L,self()|A]); +d(_, _, _, _) -> + ok. + +timestamp() -> + {Date, Time} = calendar:now_to_datetime( now() ), + {YYYY, MM, DD} = Date, + {Hour, Min, Sec} = Time, + FormatDate = + io_lib:format("~.4w-~.2.0w-~.2.0w_~.2.0w.~.2.0w.~.2.0w", + [YYYY,MM,DD,Hour,Min,Sec]), + lists:flatten(FormatDate). + diff --git a/lib/snmp/test/snmp_test_suite.erl b/lib/snmp/test/snmp_test_suite.erl new file mode 100644 index 0000000000..a6e203eba3 --- /dev/null +++ b/lib/snmp/test/snmp_test_suite.erl @@ -0,0 +1,35 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2008-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%---------------------------------------------------------------------- +%% Purpose: Each snmp test suite implements this behaviour +%%---------------------------------------------------------------------- + +-module(snmp_test_suite). + +-export([behaviour_info/1]). + +behaviour_info(callbacks) -> + [ + {all, 1}, + {init_per_testcase, 2}, + {fin_per_testcase, 2} + ]; +behaviour_info(_Other) -> + undefined. diff --git a/lib/snmp/test/test-mibs/Bitsindex-error.mib b/lib/snmp/test/test-mibs/Bitsindex-error.mib new file mode 100644 index 0000000000..0ba7467996 --- /dev/null +++ b/lib/snmp/test/test-mibs/Bitsindex-error.mib @@ -0,0 +1,94 @@ + Bitsindex-error DEFINITIONS ::= BEGIN + + IMPORTS + OBJECT-TYPE + FROM RFC-1212; + + klas1 OBJECT IDENTIFIER ::= { private 7 } + + RowStatus ::= + INTEGER { + -- the following two values are states: + -- these values may be read or written + active(1), + notInService(2), + + -- the following value is a state: + -- this value may be read, but not written + notReady(3), + + -- the following three values are + -- actions: these values may be written, + -- but are never read + createAndGo(4), + createAndWait(5), + destroy(6) + } + + + friendsTable OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas friends." + ::= { klas1 4 } + + friendsEntry OBJECT-TYPE + SYNTAX FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex } + ::= { friendsTable 1 } + + FriendsEntry ::= + SEQUENCE { + fIndex + BITS, + fName + OCTET STRING, + fStatus + INTEGER } + + fIndex OBJECT-TYPE + SYNTAX BITS {tihi(0)} + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "number of friend" + ::= { friendsEntry 1 } + + fName OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Name of friend" + ::= { friendsEntry 2 } + + fStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry 3 } + + authenticationFajlure TRAP-TYPE + ENTERPRISE klas1 + DESCRIPTION + "An authenticationFailure trap signifies that + the sending protocol entity is the addressee + of a protocol message that is not properly + authenticated. While implementations of the + SNMP must be capable of generating this trap, + they must also be capable of suppressing the + emission of such traps via an implementation- + specific mechanism." + ::= 4 + + + END + diff --git a/lib/snmp/test/test-mibs/ENTITY-MIB.mib b/lib/snmp/test/test-mibs/ENTITY-MIB.mib new file mode 100644 index 0000000000..a70c26ed3a --- /dev/null +++ b/lib/snmp/test/test-mibs/ENTITY-MIB.mib @@ -0,0 +1,784 @@ +ENTITY-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, + mib-2, NOTIFICATION-TYPE + FROM SNMPv2-SMI + TDomain, TAddress, DisplayString, TEXTUAL-CONVENTION, + AutonomousType, RowPointer, TimeStamp + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP + FROM SNMPv2-CONF; + +entityMIB MODULE-IDENTITY + LAST-UPDATED "9605160000Z" + ORGANIZATION "IETF ENTMIB Working Group" + CONTACT-INFO + " WG E-mail: [email protected] + Subscribe: [email protected] + msg body: subscribe entmib + + Keith McCloghrie + ENTMIB Working Group Chair + Cisco Systems Inc. + 170 West Tasman Drive + San Jose, CA 95134 + 408-526-5260 + + Andy Bierman + ENTMIB Working Group Editor + Cisco Systems Inc. + 170 West Tasman Drive + San Jose, CA 95134 + 408-527-3711 + DESCRIPTION + "The MIB module for representing multiple logical + entities supported by a single SNMP agent." + ::= { mib-2 47 } + +entityMIBObjects OBJECT IDENTIFIER ::= { entityMIB 1 } + +-- MIB contains four groups + +entityPhysical OBJECT IDENTIFIER ::= { entityMIBObjects 1 } +entityLogical OBJECT IDENTIFIER ::= { entityMIBObjects 2 } + + +entityMapping OBJECT IDENTIFIER ::= { entityMIBObjects 3 } +entityGeneral OBJECT IDENTIFIER ::= { entityMIBObjects 4 } + + +-- Textual Conventions +PhysicalIndex ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "An arbitrary value which uniquely identifies the physical + entity. The value is a small positive integer; index values + for different physical entities are not necessarily + contiguous." + SYNTAX INTEGER (1..2147483647) + + +PhysicalClass ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "An enumerated value which provides an indication of the + general hardware type of a particular physical entity." + SYNTAX INTEGER { + other(1), + unknown(2), + chassis(3), + backplane(4), + container(5), -- e.g. slot or daughter-card holder + powerSupply(6), + fan(7), + sensor(8), + module(9), -- e.g. plug-in card or daughter-card + port(10) + } + +-- The Physical Entity Table + +entPhysicalTable OBJECT-TYPE + SYNTAX SEQUENCE OF EntPhysicalEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table contains one row per physical entity. There is + always at least one row for an 'overall' physical entity." + ::= { entityPhysical 1 } + +entPhysicalEntry OBJECT-TYPE + SYNTAX EntPhysicalEntry + MAX-ACCESS not-accessible + STATUS current + + + DESCRIPTION + "Information about a particular physical entity. + + Each entry provides objects (entPhysicalDescr, + entPhysicalVendorType, and entPhysicalClass) to help an NMS + identify and characterize the entry, and objects + (entPhysicalContainedIn and entPhysicalParentRelPos) to help + an NMS relate the particular entry to other entries in this + table." + INDEX { entPhysicalIndex } + ::= { entPhysicalTable 1 } + +EntPhysicalEntry ::= SEQUENCE { + entPhysicalIndex PhysicalIndex, + entPhysicalDescr DisplayString, + entPhysicalVendorType AutonomousType, + entPhysicalContainedIn INTEGER, + entPhysicalClass PhysicalClass, + entPhysicalParentRelPos INTEGER, + entPhysicalName DisplayString +} + +entPhysicalIndex OBJECT-TYPE + SYNTAX PhysicalIndex + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The index for this entry." + ::= { entPhysicalEntry 1 } + +entPhysicalDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of physical entity. This object + should contain a string which identifies the manufacturer's + name for the physical entity, and should be set to a + distinct value for each version or model of the physical + entity. " + ::= { entPhysicalEntry 2 } + +entPhysicalVendorType OBJECT-TYPE + SYNTAX AutonomousType + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An indication of the vendor-specific hardware type of the + + + physical entity. Note that this is different from the + definition of MIB-II's sysObjectID. + + An agent should set this object to a enterprise-specific + registration identifier value indicating the specific + equipment type in detail. The associated instance of + entPhysicalClass is used to indicate the general type of + hardware device. + + If no vendor-specific registration identifier exists for + this physical entity, or the value is unknown by this agent, + then the value { 0 0 } is returned." + ::= { entPhysicalEntry 3 } + +entPhysicalContainedIn OBJECT-TYPE + SYNTAX INTEGER (0..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of entPhysicalIndex for the physical entity which + 'contains' this physical entity. A value of zero indicates + this physical entity is not contained in any other physical + entity. Note that the set of 'containment' relationships + define a strict hierarchy; that is, recursion is not + allowed." + ::= { entPhysicalEntry 4 } + +entPhysicalClass OBJECT-TYPE + SYNTAX PhysicalClass + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An indication of the general hardware type of the physical + entity. + + An agent should set this object to the standard enumeration + value which most accurately indicates the general class of + the physical entity, or the primary class if there is more + than one. + + If no appropriate standard registration identifier exists + for this physical entity, then the value 'other(1)' is + returned. If the value is unknown by this agent, then the + value 'unknown(2)' is returned." + ::= { entPhysicalEntry 5 } + +entPhysicalParentRelPos OBJECT-TYPE + SYNTAX INTEGER (-1..2147483647) + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An indication of the relative position of this 'child' + component among all its 'sibling' components. Sibling + components are defined as entPhysicalEntries which share the + same instance values of each of the entPhysicalContainedIn + and entPhysicalClass objects. + + An NMS can use this object to identify the relative ordering + for all sibling components of a particular parent + (identified by the entPhysicalContainedIn instance in each + sibling entry). + + This value should match any external labeling of the + physical component if possible. For example, for a module + labeled as 'card #3', entPhysicalParentRelPos should have + the value '3'. + + If the physical position of this component does not match + any external numbering or clearly visible ordering, then + user documentation or other external reference material + should be used to determine the parent-relative position. If + this is not possible, then the the agent should assign a + consistent (but possibly arbitrary) ordering to a given set + of 'sibling' components, perhaps based on internal + representation of the components. + + If the agent cannot determine the parent-relative position + for some reason, or if the associated value of + entPhysicalContainedIn is '0', then the value '-1' is + returned. Otherwise a non-negative integer is returned, + indicating the parent-relative position of this physical + entity. + + Parent-relative ordering normally starts from '1' and + continues to 'N', where 'N' represents the highest + positioned child entity. However, if the physical entities + (e.g. slots) are labeled from a starting position of zero, + then the first sibling should be associated with a + entPhysicalParentRelPos value of '0'. Note that this + ordering may be sparse or dense, depending on agent + implementation. + + The actual values returned are not globally meaningful, as + each 'parent' component may use different numbering + algorithms. The ordering is only meaningful among siblings + of the same parent component. + + + The agent should retain parent-relative position values + across reboots, either through algorithmic assignment or use + of non-volatile storage." + ::= { entPhysicalEntry 6 } + + +entPhysicalName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The textual name of the physical entity. The value of this + object should be the name of the component as assigned by + the local device and should be suitable for use in commands + entered at the device's `console'. This might be a text + name, such as `console' or a simple component number (e.g. + port or module number), such as `1', depending on the + physical component naming syntax of the device. + + If there is no local name, or this object is otherwise not + applicable, then this object contains a zero-length string. + + Note that the value of entPhysicalName for two physical + entities will be the same in the event that the console + interface does not distinguish between them, e.g., slot-1 + and the card in slot-1." + ::= { entPhysicalEntry 7 } + +-- The Logical Entity Table +entLogicalTable OBJECT-TYPE + SYNTAX SEQUENCE OF EntLogicalEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table contains one row per logical entity. At least + one entry must exist." + ::= { entityLogical 1 } + +entLogicalEntry OBJECT-TYPE + SYNTAX EntLogicalEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Information about a particular logical entity. Entities + may be managed by this agent or other SNMP agents (possibly) + in the same chassis." + INDEX { entLogicalIndex } + ::= { entLogicalTable 1 } + + +EntLogicalEntry ::= SEQUENCE { + entLogicalIndex INTEGER, + entLogicalDescr DisplayString, + entLogicalType AutonomousType, + entLogicalCommunity OCTET STRING, + entLogicalTAddress TAddress, + entLogicalTDomain TDomain +} + +entLogicalIndex OBJECT-TYPE + SYNTAX INTEGER (1..2147483647) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The value of this object uniquely identifies the logical + entity. The value is a small positive integer; index values + for different logical entities are are not necessarily + contiguous." + ::= { entLogicalEntry 1 } + +entLogicalDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the logical entity. This object + should contain a string which identifies the manufacturer's + name for the logical entity, and should be set to a distinct + value for each version of the logical entity. " + ::= { entLogicalEntry 2 } + +entLogicalType OBJECT-TYPE + SYNTAX AutonomousType + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An indication of the type of logical entity. This will + typically be the OBJECT IDENTIFIER name of the node in the + SMI's naming hierarchy which represents the major MIB + module, or the majority of the MIB modules, supported by the + logical entity. For example: + a logical entity of a regular host/router -> mib-2 + a logical entity of a 802.1d bridge -> dot1dBridge + a logical entity of a 802.3 repeater -> snmpDot3RptrMgmt + If an appropriate node in the SMI's naming hierarchy cannot + be identified, the value 'mib-2' should be used." + ::= { entLogicalEntry 3 } + + + +entLogicalCommunity OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (1..255)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An SNMPv1 or SNMPv2C community-string which can be used to + access detailed management information for this logical + entity. The agent should allow read access with this + community string (to an appropriate subset of all managed + objects) and may also choose to return a community string + based on the privileges of the request used to read this + object. Note that an agent may choose to return a community + string with read-only privileges, even if this object is + accessed with a read-write community string. However, the + agent must take care not to return a community string which + allows more privileges than the community string used to + access this object. + + A compliant SNMP agent may wish to conserve naming scopes by + representing multiple logical entities in a single 'main' + naming scope. This is possible when the logical entities + represented by the same value of entLogicalCommunity have no + object instances in common. For example, 'bridge1' and + 'repeater1' may be part of the main naming scope, but at + least one additional community string is needed to represent + 'bridge2' and 'repeater2'. + + Logical entities 'bridge1' and 'repeater1' would be + represented by sysOREntries associated with the 'main' + naming scope. + + For agents not accessible via SNMPv1 or SNMPv2C, the value + of this object is the empty-string." + ::= { entLogicalEntry 4 } + +entLogicalTAddress OBJECT-TYPE + SYNTAX TAddress + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The transport service address by which the logical entity + receives network management traffic, formatted according to + the corresponding value of entLogicalTDomain. + + For snmpUDPDomain, a TAddress is 6 octets long, the initial + 4 octets containing the IP-address in network-byte order and + the last 2 containing the UDP port in network-byte order. + Consult 'Transport Mappings for Version 2 of the Simple + + + Network Management Protocol' (RFC 1906 [8]) for further + information on snmpUDPDomain." + ::= { entLogicalEntry 5 } + +entLogicalTDomain OBJECT-TYPE + SYNTAX TDomain + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Indicates the kind of transport service by which the + logical entity receives network management traffic. + Possible values for this object are presently found in the + Transport Mappings for SNMPv2 document (RFC 1906 [8])." + ::= { entLogicalEntry 6 } + +entLPMappingTable OBJECT-TYPE + SYNTAX SEQUENCE OF EntLPMappingEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table contains zero or more rows of logical entity to + physical equipment associations. For each logical entity + known by this agent, there are zero or more mappings to the + physical resources which are used to realize that logical + entity. + + An agent should limit the number and nature of entries in + this table such that only meaningful and non-redundant + information is returned. For example, in a system which + contains a single power supply, mappings between logical + entities and the power supply are not useful and should not + be included. + + Also, only the most appropriate physical component which is + closest to the root of a particular containment tree should + be identified in an entLPMapping entry. + + For example, suppose a bridge is realized on a particular + module, and all ports on that module are ports on this + bridge. A mapping between the bridge and the module would be + useful, but additional mappings between the bridge and each + of the ports on that module would be redundant (since the + entPhysicalContainedIn hierarchy can provide the same + information). If, on the other hand, more than one bridge + was utilizing ports on this module, then mappings between + each bridge and the ports it used would be appropriate. + + Also, in the case of a single backplane repeater, a mapping + + + for the backplane to the single repeater entity is not + necessary." + ::= { entityMapping 1 } + +entLPMappingEntry OBJECT-TYPE + SYNTAX EntLPMappingEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Information about a particular logical entity to physical + equipment association. Note that the nature of the + association is not specifically identified in this entry. It + is expected that sufficient information exists in the MIBs + used to manage a particular logical entity to infer how + physical component information is utilized." + INDEX { entLogicalIndex, entLPPhysicalIndex } + ::= { entLPMappingTable 1 } + +EntLPMappingEntry ::= SEQUENCE { + entLPPhysicalIndex PhysicalIndex +} + +entLPPhysicalIndex OBJECT-TYPE + SYNTAX PhysicalIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of this object identifies the index value of a + particular entPhysicalEntry associated with the indicated + entLogicalEntity." + ::= { entLPMappingEntry 1 } + +-- logical entity/component to alias table +entAliasMappingTable OBJECT-TYPE + SYNTAX SEQUENCE OF EntAliasMappingEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table contains zero or more rows, representing + mappings of logical entity and physical component to + external MIB identifiers. Each physical port in the system + may be associated with a mapping to an external identifier, + which itself is associated with a particular logical + entity's naming scope. A 'wildcard' mechanism is provided to + indicate that an identifier is associated with more than one + logical entity." + ::= { entityMapping 2 } + + + +entAliasMappingEntry OBJECT-TYPE + SYNTAX EntAliasMappingEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Information about a particular physical equipment, logical + entity to external identifier binding. Each logical + entity/physical component pair may be associated with one + alias mapping. The logical entity index may also be used as + a 'wildcard' (refer to the entAliasLogicalIndexOrZero object + DESCRIPTION clause for details.) + + Note that only entPhysicalIndex values which represent + physical ports (i.e. associated entPhysicalClass value is + 'port(10)') are permitted to exist in this table." + INDEX { entPhysicalIndex, entAliasLogicalIndexOrZero } + ::= { entAliasMappingTable 1 } + +EntAliasMappingEntry ::= SEQUENCE { + entAliasLogicalIndexOrZero INTEGER, + entAliasMappingIdentifier RowPointer +} + +entAliasLogicalIndexOrZero OBJECT-TYPE + SYNTAX INTEGER (0..2147483647) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The value of this object uniquely identifies the logical + entity which defines the naming scope for the associated + instance of the 'entAliasMappingIdentifier' object. + + If this object has a non-zero value, then it identifies the + logical entity named by the same value of entLogicalIndex. + + If this object has a value of zero, then the mapping between + the physical component and the alias identifier for this + entAliasMapping entry is associated with all unspecified + logical entities. That is, a value of zero (the default + mapping) identifies any logical entity which does not have + an explicit entry in this table for a particular + entPhysicalIndex/entAliasMappingIdentifier pair. + + For example, to indicate that a particular interface (e.g. + physical component 33) is identified by the same value of + ifIndex for all logical entities, the following instance + might exist: + + + + entAliasMappingIdentifier.33.0 = ifIndex.5 + + In the event an entPhysicalEntry is associated differently + for some logical entities, additional entAliasMapping + entries may exist, e.g.: + + entAliasMappingIdentifier.33.0 = ifIndex.6 + entAliasMappingIdentifier.33.4 = ifIndex.1 + entAliasMappingIdentifier.33.5 = ifIndex.1 + entAliasMappingIdentifier.33.10 = ifIndex.12 + + Note that entries with non-zero entAliasLogicalIndexOrZero + index values have precedence over any zero-indexed entry. In + this example, all logical entities except 4, 5, and 10, + associate physical entity 33 with ifIndex.6." + ::= { entAliasMappingEntry 1 } + + +entAliasMappingIdentifier OBJECT-TYPE + SYNTAX RowPointer + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of this object identifies a particular conceptual + row associated with the indicated entPhysicalIndex and + entLogicalIndex pair. + + Since only physical ports are modeled in this table, only + entries which represent interfaces or ports are allowed. If + an ifEntry exists on behalf of a particular physical port, + then this object should identify the associated 'ifEntry'. + For repeater ports, the appropriate row in the + 'rptrPortGroupTable' should be identified instead. + + For example, suppose a physical port was represented by + entPhysicalEntry.3, entLogicalEntry.15 existed for a + repeater, and entLogicalEntry.22 existed for a bridge. Then + there might be two related instances of + entAliasMappingIdentifier: + entAliasMappingIdentifier.3.15 == rptrPortGroupIndex.5.2 + entAliasMappingIdentifier.3.22 == ifIndex.17 + It is possible that other mappings (besides interfaces and + repeater ports) may be defined in the future, as required. + + Bridge ports are identified by examining the Bridge MIB and + appropriate ifEntries associated with each 'dot1dBasePort', + and are thus not represented in this table." + ::= { entAliasMappingEntry 2 } + + +-- physical mapping table +entPhysicalContainsTable OBJECT-TYPE + SYNTAX SEQUENCE OF EntPhysicalContainsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table which exposes the container/containee relationships + between physical entities. This table provides equivalent + information found by constructing the virtual containment + tree for a given entPhysicalTable but in a more direct + format." + ::= { entityMapping 3 } + +entPhysicalContainsEntry OBJECT-TYPE + SYNTAX EntPhysicalContainsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A single container/containee relationship." + INDEX { entPhysicalIndex, entPhysicalChildIndex } + ::= { entPhysicalContainsTable 1 } + +EntPhysicalContainsEntry ::= SEQUENCE { + entPhysicalChildIndex PhysicalIndex +} + +entPhysicalChildIndex OBJECT-TYPE + SYNTAX PhysicalIndex + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of entPhysicalIndex for the contained physical + entity." + ::= { entPhysicalContainsEntry 1 } + +-- last change time stamp for the whole MIB +entLastChangeTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time any of these events + occur: + * a conceptual row is created or deleted in any + of these tables: + - entPhysicalTable + - entLogicalTable + - entLPMappingTable + + + - entAliasMappingTable + - entPhysicalContainsTable + + * any instance in the following list of objects + changes value: + - entPhysicalDescr + - entPhysicalVendorType + - entPhysicalContainedIn + - entPhysicalClass + - entPhysicalParentRelPos + - entPhysicalName + - entLogicalDescr + - entLogicalType + - entLogicalCommunity + - entLogicalTAddress + - entLogicalTDomain + - entAliasMappingIdentifier " + ::= { entityGeneral 1 } + +-- Entity MIB Trap Definitions +entityMIBTraps OBJECT IDENTIFIER ::= { entityMIB 2 } +entityMIBTrapPrefix OBJECT IDENTIFIER ::= { entityMIBTraps 0 } + +entConfigChange NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "An entConfigChange trap is sent when the value of + entLastChangeTime changes. It can be utilized by an NMS to + trigger logical/physical entity table maintenance polls. + + An agent must not generate more than one entConfigChange + 'trap-event' in a five second period, where a 'trap-event' + is the transmission of a single trap PDU to a list of trap + destinations. If additional configuration changes occur + within the five second 'throttling' period, then these + trap-events should be suppressed by the agent. An NMS should + periodically check the value of entLastChangeTime to detect + any missed entConfigChange trap-events, e.g. due to + throttling or transmission loss." + ::= { entityMIBTrapPrefix 1 } + +-- conformance information +entityConformance OBJECT IDENTIFIER ::= { entityMIB 3 } + +entityCompliances OBJECT IDENTIFIER ::= { entityConformance 1 } +entityGroups OBJECT IDENTIFIER ::= { entityConformance 2 } + +-- compliance statements + + +entityCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for SNMP entities which implement + the Entity MIB." + MODULE -- this module + MANDATORY-GROUPS { entityPhysicalGroup, + entityLogicalGroup, + entityMappingGroup, + entityGeneralGroup, + entityNotificationsGroup } + ::= { entityCompliances 1 } + +-- MIB groupings + +entityPhysicalGroup OBJECT-GROUP + OBJECTS { + entPhysicalDescr, + entPhysicalVendorType, + entPhysicalContainedIn, + entPhysicalClass, + entPhysicalParentRelPos, + entPhysicalName + } + STATUS current + DESCRIPTION + "The collection of objects which are used to represent + physical system components, for which a single agent + provides management information." + ::= { entityGroups 1 } + +entityLogicalGroup OBJECT-GROUP + OBJECTS { + entLogicalDescr, + entLogicalType, + entLogicalCommunity, + entLogicalTAddress, + entLogicalTDomain + } + STATUS current + DESCRIPTION + "The collection of objects which are used to represent the + list of logical entities for which a single agent provides + management information." + ::= { entityGroups 2 } + +entityMappingGroup OBJECT-GROUP + OBJECTS { + + + entLPPhysicalIndex, + entAliasMappingIdentifier, + entPhysicalChildIndex + } + STATUS current + DESCRIPTION + "The collection of objects which are used to represent the + associations between multiple logical entities, physical + components, interfaces, and port identifiers for which a + single agent provides management information." + ::= { entityGroups 3 } + +entityGeneralGroup OBJECT-GROUP + OBJECTS { + entLastChangeTime + } + STATUS current + DESCRIPTION + "The collection of objects which are used to represent + general entity information for which a single agent provides + management information." + ::= { entityGroups 4 } + +entityNotificationsGroup NOTIFICATION-GROUP + NOTIFICATIONS { entConfigChange } + STATUS current + DESCRIPTION + "The collection of notifications used to indicate Entity MIB + data consistency and general status information." + ::= { entityGroups 5 } + + +END + + + diff --git a/lib/snmp/test/test-mibs/INTERNAL-MIB.mib b/lib/snmp/test/test-mibs/INTERNAL-MIB.mib new file mode 100644 index 0000000000..62d3777fc2 --- /dev/null +++ b/lib/snmp/test/test-mibs/INTERNAL-MIB.mib @@ -0,0 +1,463 @@ +INTERNAL-MIB DEFINITIONS ::= BEGIN + + IMPORTS + IpAddress + FROM RFC1155-SMI + DisplayString, mib-2 + FROM RFC1213-MIB + OBJECT-TYPE + FROM RFC-1212 + TruthValue, RowStatus + FROM STANDARD-MIB + ; + + + +-- Object Identifiers for all the Managed Objects must be defined +-- if this MIB (or parts of it) shall be loaded. +-- It is entirely up to the implementation to assign OIDs for the +-- objects. The SNMP agent does not rely on the OIDs, but on the +-- symbolic names of the managed objects. + +ericsson OBJECT IDENTIFIER ::= {enterprises 193} +snmpAdm OBJECT IDENTIFIER ::= {ericsson 1} +community OBJECT IDENTIFIER ::= {snmpAdm 1} +trap OBJECT IDENTIFIER ::= {snmpAdm 2} +view OBJECT IDENTIFIER ::= {snmpAdm 3} + + + -- Datatype + + StorageType ::= + INTEGER { + other(1), -- eh? + volatile(2), -- e.g., in RAM + nonVolatile(3), -- e.g., in NVRAM + permanent(4) -- e.g., in ROM + } + + -- Managed Objects + + intCommunityTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntCommunityEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "This table defines access for the different + communities. + + When a request comes from a certain ip address, + referring to a community string, the mib view + and access corresponding to these are looked up + in this table. Then the operation is validatated against + the access, and all requested objects validated against + the mib view." + ::= { community 1} + + intCommunityEntry OBJECT-TYPE + SYNTAX IntCommunityEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + INDEX { intCommunityDestination, intCommunityString } + ::= { intCommunityTable 1 } + + IntCommunityEntry ::= + SEQUENCE { + intCommunityDestination IpAddress, + intCommunityString DisplayString, + intCommunityViewIndex INTEGER, + intCommunityAccess INTEGER, + intCommunityStatus RowStatus + } + + intCommunityDestination OBJECT-TYPE + SYNTAX IpAddress + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The ip address of a management station. The special + ip address {0.0.0.0} is a wildcard, meaning all possible + ip addresses. In this way, access can be granted to all + ip addressed for some communities." + ::= { intCommunityEntry 1 } + + intCommunityString OBJECT-TYPE + SYNTAX DisplayString + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The community string, defining the community." + ::= { intCommunityEntry 2 } + + intCommunityViewIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Identifies a mib view. Index into the + intViewTable." + ::= { intCommunityEntry 3 } + + intCommunityAccess OBJECT-TYPE + SYNTAX INTEGER { read(1), readWrite(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Defines which operations the manager can perform + on the objects in the mib view." + ::= { intCommunityEntry 4 } + + intCommunityStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row in the + intCommunityTable." + ::= { intCommunityEntry 5 } + + intAgentIpAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The IP address of this agent." + ::= { community 2 } + + intAgentUDPPort OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The UDP port the agent listens to." + ::= { community 3 } + + intAgentMaxPacketSize OBJECT-TYPE + SYNTAX INTEGER (484..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum packet size in bytes this agent will send to a + manager." + ::= { community 4 } + + + intAddressTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntAddressEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "This table holds UDP related information on each known + management station." + ::= { community 5 } + + + intAddressEntry OBJECT-TYPE + SYNTAX IntAddressEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + INDEX { intAddressDestination } + ::= { intAddressTable 1 } + + IntAddressEntry ::= + SEQUENCE { + intAddressDestination IpAddress, + intAddressUDPPort INTEGER, + intAddressMaxPacketSize INTEGER (484..65535), + intAddressStatus RowStatus + } + + intAddressDestination OBJECT-TYPE + SYNTAX IpAddress + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The ip address of the management station." + ::= { intAddressEntry 1 } + + intAddressUDPPort OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The UDP port to which traps will be sent to + this destination." + DEFVAL { 162 } + ::= { intAddressEntry 2 } + + intAddressMaxPacketSize OBJECT-TYPE + SYNTAX INTEGER (484..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The maximum packet size in bytes for Messages + sent to this destination. The max size of a packet + sent to this destination will be the minumim of + this variable and agentMaxPacketSize.0." + ::= { intAddressEntry 3 } + + intAddressStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row in the + intAddressTable." + ::= { intAddressEntry 4 } + + intTrapDestTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntTrapDestEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The intTrapDestTable defines to which destination all traps + for a specific community should be sent." + ::= { trap 1 } + + intTrapDestEntry OBJECT-TYPE + SYNTAX IntTrapDestEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + INDEX { intTrapDestCommunityString, intTrapDestDestination } + ::= { intTrapDestTable 1 } + + IntTrapDestEntry ::= + SEQUENCE { + intTrapDestCommunityString DisplayString, + intTrapDestDestination IpAddress, + intTrapDestStatus RowStatus, + intTrapDestSnmpVersion INTEGER + } + + intTrapDestCommunityString OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + ::= { intTrapDestEntry 1 } + + intTrapDestDestination OBJECT-TYPE + SYNTAX IpAddress + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "" + ::= { intTrapDestEntry 2 } + + intTrapDestStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row in the + intTrapDestTable." + ::= { intTrapDestEntry 3 } + + intTrapDestSnmpVersion OBJECT-TYPE + SYNTAX INTEGER { v1(1), v2c(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The SNMP version of the manager. If it is v1, + SNMPv1Traps are sent. If it is v2c, + SNMPv2Traps are sent" + ::= { intTrapDestEntry 4 } + + intViewTable OBJECT-TYPE + SYNTAX SEQUENCE OF IntViewEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Locally held information about the MIB views + known to this agent. + + Each MIB view is defined by two + collections of view subtrees: the included view + subtrees, and the excluded view subtrees. Every + such subtree, both included and excluded, is + defined in this table. + + To determine if a particular object instance is in + a particular MIB view, compare the object + instance's OBJECT IDENTIFIER with each of the MIB + view's entries in this table. If none match, then + the object instance is not in the MIB view. If + one or more match, then the object instance is + included in, or excluded from, the MIB view + according to the value of viewType in the entry + whose value of viewSubtree has the most sub- + identifiers. If multiple entries match and have + the same number of sub-identifiers, then the + lexicographically greatest instance of viewType + determines the inclusion or exclusion. + + An object instance's OBJECT IDENTIFIER X matches + an entry in this table when the number of sub- + identifiers in X is at least as many as in the + value of viewSubtree for the entry, and each sub- + identifier in the value of viewSubtree matches its + corresponding sub-identifier in X. Two sub- + identifiers match either if the corresponding bit + of viewMask is zero (the 'wild card' value), or if + they are equal. + + Due to this 'wild card' capability, we introduce + the term, a 'family' of view subtrees, to refer to + the set of subtrees defined by a particular + combination of values of viewSubtree and viewMask. + In the case where no 'wild card' is defined in + viewMask, the family of view subtrees reduces to a + single view subtree." + ::= { view 1 } + + intViewEntry OBJECT-TYPE + SYNTAX IntViewEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information on a particular family of view + subtrees included in or excluded from a particular + MIB view. + + Implementations must not restrict the number of + families of view subtrees for a given MIB view, + except as dictated by resource constraints on the + overall number of entries in the viewTable." + INDEX { intViewIndex, intViewSubtree } + ::= { intViewTable 1 } + + IntViewEntry ::= + SEQUENCE { + intViewIndex INTEGER, + intViewSubtree OBJECT IDENTIFIER, + intViewMask OCTET STRING, + intViewType INTEGER, + intViewStorageType StorageType, + intViewStatus RowStatus + } + + + intViewIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A unique value for each MIB view. The value for + each MIB view must remain constant at least from + one re-initialization of the entity's network + management system to the next re-initialization." + ::= { intViewEntry 1 } + + intViewSubtree OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A MIB subtree." + ::= { intViewEntry 2 } + + intViewMask OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..16)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The bit mask which, in combination with the + corresponding instance of viewSubtree, defines a + family of view subtrees. + + Each bit of this bit mask corresponds to a sub- + identifier of viewSubtree, with the most + significant bit of the i-th octet of this octet + string value (extended if necessary, see below) + corresponding to the (8*i - 7)-th sub-identifier, + and the least significant bit of the i-th octet of + this octet string corresponding to the (8*i)-th + sub-identifier, where i is in the range 1 through + 16. + + Each bit of this bit mask specifies whether or not + the corresponding sub-identifiers must match when + determining if an OBJECT IDENTIFIER is in this + family of view subtrees; a '1' indicates that an + exact match must occur; a '0' indicates 'wild + card', i.e., any sub-identifier value matches. + + + Thus, the OBJECT IDENTIFIER X of an object + instance is contained in a family of view subtrees + if the following criteria are met: + + for each sub-identifier of the value of + viewSubtree, either: + + the i-th bit of viewMask is 0, or + + the i-th sub-identifier of X is equal to + the i-th sub-identifier of the value of + viewSubtree. + + If the value of this bit mask is M bits long and + there are more than M sub-identifiers in the + corresponding instance of viewSubtree, then the + bit mask is extended with 1's to be the required + length. + + Note that when the value of this object is the + zero-length string, this extension rule results in + a mask of all-1's being used (i.e., no 'wild + card'), and the family of view subtrees is the one + view subtree uniquely identified by the + corresponding instance of viewSubtree." + DEFVAL { ''H } + ::= { intViewEntry 3 } + + + intViewType OBJECT-TYPE + SYNTAX INTEGER { + included(1), + excluded(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of a particular family of view + subtrees within the particular + MIB view. The value 'included(1)' indicates that + the corresponding instances of viewSubtree and + viewMask define a family of view subtrees included + in the MIB view. The value 'excluded(2)' + indicates that the corresponding instances of + viewSubtree and viewMask define a family of view + subtrees excluded from the MIB view." + DEFVAL { included } + ::= { intViewEntry 4 } + + intViewStorageType OBJECT-TYPE + SYNTAX StorageType + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The storage type for this conceptual row in the + intViewTable." + DEFVAL { nonVolatile } + ::= { intViewEntry 5 } + + intViewStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row in the + intViewTable." + ::= { intViewEntry 6 } + + + +END diff --git a/lib/snmp/test/test-mibs/Klas1.mib b/lib/snmp/test/test-mibs/Klas1.mib new file mode 100644 index 0000000000..987c7a6d95 --- /dev/null +++ b/lib/snmp/test/test-mibs/Klas1.mib @@ -0,0 +1,118 @@ + Klas1 DEFINITIONS ::= BEGIN + + IMPORTS + OBJECT-TYPE + FROM RFC-1212; + + klas1 OBJECT IDENTIFIER ::= { private 7 } + + DisplayString ::= + OCTET STRING + + + Q2 ::= DisplayString (SIZE (0..25)) + + RowStatus ::= + INTEGER { + -- the following two values are states: + -- these values may be read or written + active(1), + notInService(2), + + -- the following value is a state: + -- this value may be read, but not written + notReady(3), + + -- the following three values are + -- actions: these values may be written, + -- but are never read + createAndGo(4), + createAndWait(5), + destroy(6) + } + + + fint OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + printable ASCII characters." + ::= { klas1 0 1 } + + fname OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + printable ASCII characters." + ::= { klas1 1 } + + friendsTable OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas friends." + ::= { klas1 4 } + + friendsEntry OBJECT-TYPE + SYNTAX FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex } + ::= { friendsTable 1 } + + FriendsEntry ::= + SEQUENCE { + fIndex + INTEGER, + fName + OCTET STRING, + fStatus + INTEGER } + + fIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "number of friend" + ::= { friendsEntry 1 } + + fName OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Name of friend" + ::= { friendsEntry 2 } + + fStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry 3 } + + authenticationFajlure TRAP-TYPE + ENTERPRISE klas1 + DESCRIPTION + "An authenticationFailure trap signifies that + the sending protocol entity is the addressee + of a protocol message that is not properly + authenticated. While implementations of the + SNMP must be capable of generating this trap, + they must also be capable of suppressing the + emission of such traps via an implementation- + specific mechanism." + ::= 4 + + + END + diff --git a/lib/snmp/test/test-mibs/Oid1-error.mib b/lib/snmp/test/test-mibs/Oid1-error.mib new file mode 100644 index 0000000000..ee9c649f9d --- /dev/null +++ b/lib/snmp/test/test-mibs/Oid1-error.mib @@ -0,0 +1,26 @@ + Oid1-error DEFINITIONS ::= BEGIN + + IMPORTS + OBJECT-TYPE + FROM RFC-1212; + + klas1 OBJECT IDENTIFIER ::= { private 7 } + + ok OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "" + ::= { klas1 0 1 } + + error OBJECT-TYPE + SYNTAX TestOfUndefinedType (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "" + ::= { klas1 1 0} + + END + diff --git a/lib/snmp/test/test-mibs/README b/lib/snmp/test/test-mibs/README new file mode 100644 index 0000000000..f23d3151c2 --- /dev/null +++ b/lib/snmp/test/test-mibs/README @@ -0,0 +1,19 @@ +MIBs ending with *-error.mib should give compilation error. No others. + +All standards MIBs should be original, without modifications. +*If* there is some small modification for some reason you shall be +able to find a comment about it by searching "erlsnmpmodification". +Tickets are found in comments (search "OTP-<no>"). + +One good compilation order: + +snmpc:compile("RMON-MIB"). +snmpc:compile("RFC1271-MIB"). +snmpc:compile("TOKEN-RING-RMON-MIB"). +snmpc:compile("SNMPv2-TC"). +snmpc:compile("RMON2-MIB"). +snmpc:compile("ENTITY-MIB"). +snmpc:compile("SNMPv2-MIB"). +snmpc:compile("SNMPv2-USEC-MIB"). +snmpc:compile("STANDARD-MIB"). +snmpc:compile("INTERNAL-MIB"). diff --git a/lib/snmp/test/test-mibs/RFC1213-MIB.mib b/lib/snmp/test/test-mibs/RFC1213-MIB.mib new file mode 100644 index 0000000000..0421e64d62 --- /dev/null +++ b/lib/snmp/test/test-mibs/RFC1213-MIB.mib @@ -0,0 +1,2888 @@ + RFC1213-MIB DEFINITIONS ::= BEGIN + + IMPORTS + mgmt, NetworkAddress, IpAddress, Counter, Gauge, + TimeTicks + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212; + + -- This MIB module uses the extended OBJECT-TYPE macro as + -- defined in [14]; + + + -- MIB-II (same prefix as MIB-I) + + mib-2 OBJECT IDENTIFIER ::= { mgmt 1 } + + -- textual conventions + + DisplayString ::= + OCTET STRING + -- This data type is used to model textual information taken + -- from the NVT ASCII character set. By convention, objects + -- with this syntax are declared as having + + + + -- + -- SIZE (0..255) + + PhysAddress ::= + OCTET STRING + -- This data type is used to model media addresses. For many + -- types of media, this will be in a binary representation. + -- For example, an ethernet address would be represented as + -- a string of 6 octets. + + + -- groups in MIB-II + + system OBJECT IDENTIFIER ::= { mib-2 1 } + + interfaces OBJECT IDENTIFIER ::= { mib-2 2 } + + at OBJECT IDENTIFIER ::= { mib-2 3 } + + ip OBJECT IDENTIFIER ::= { mib-2 4 } + + icmp OBJECT IDENTIFIER ::= { mib-2 5 } + + tcp OBJECT IDENTIFIER ::= { mib-2 6 } + + udp OBJECT IDENTIFIER ::= { mib-2 7 } + + egp OBJECT IDENTIFIER ::= { mib-2 8 } + + -- historical (some say hysterical) + -- cmot OBJECT IDENTIFIER ::= { mib-2 9 } + + transmission OBJECT IDENTIFIER ::= { mib-2 10 } + + snmp OBJECT IDENTIFIER ::= { mib-2 11 } + + + -- the System group + + -- Implementation of the System group is mandatory for all + -- systems. If an agent is not configured to have a value + -- for any of these variables, a string of length 0 is + -- returned. + + sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "A textual description of the entity. This value + should include the full name and version + identification of the system's hardware type, + software operating-system, and networking + software. It is mandatory that this only contain + printable ASCII characters." + ::= { system 1 } + + sysObjectID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The vendor's authoritative identification of the + network management subsystem contained in the + entity. This value is allocated within the SMI + enterprises subtree (1.3.6.1.4.1) and provides an + easy and unambiguous means for determining `what + kind of box' is being managed. For example, if + vendor `Flintstones, Inc.' was assigned the + subtree 1.3.6.1.4.1.4242, it could assign the + identifier 1.3.6.1.4.1.4242.1.1 to its `Fred + Router'." + ::= { system 2 } + + sysUpTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The time (in hundredths of a second) since the + network management portion of the system was last + re-initialized." + ::= { system 3 } + + sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The textual identification of the contact person + for this managed node, together with information + on how to contact this person." + ::= { system 4 } + + sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + + + + + + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An administratively-assigned name for this + managed node. By convention, this is the node's + fully-qualified domain name." + ::= { system 5 } + + sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The physical location of this node (e.g., + `telephone closet, 3rd floor')." + ::= { system 6 } + + sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A value which indicates the set of services that + this entity primarily offers. + + The value is a sum. This sum initially takes the + value zero, Then, for each layer, L, in the range + 1 through 7, that this node performs transactions + for, 2 raised to (L - 1) is added to the sum. For + example, a node which performs primarily routing + functions would have a value of 4 (2^(3-1)). In + contrast, a node which is a host offering + application services would have a value of 72 + (2^(4-1) + 2^(7-1)). Note that in the context of + the Internet suite of protocols, values should be + calculated accordingly: + + layer functionality + 1 physical (e.g., repeaters) + 2 datalink/subnetwork (e.g., bridges) + 3 internet (e.g., IP gateways) + 4 end-to-end (e.g., IP hosts) + 7 applications (e.g., mail relays) + + For systems including OSI protocols, layers 5 and + 6 may also be counted." + ::= { system 7 } + + + + + + + -- the Interfaces group + + -- Implementation of the Interfaces group is mandatory for + -- all systems. + + ifNumber OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of network interfaces (regardless of + their current state) present on this system." + ::= { interfaces 1 } + + + -- the Interfaces table + + -- The Interfaces table contains information on the entity's + -- interfaces. Each interface is thought of as being + -- attached to a `subnetwork'. Note that this term should + -- not be confused with `subnet' which refers to an + -- addressing partitioning scheme used in the Internet suite + -- of protocols. + + ifTable OBJECT-TYPE + SYNTAX SEQUENCE OF IfEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of interface entries. The number of + entries is given by the value of ifNumber." + ::= { interfaces 2 } + + ifEntry OBJECT-TYPE + SYNTAX IfEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "An interface entry containing objects at the + subnetwork layer and below for a particular + interface." + INDEX { ifIndex } + ::= { ifTable 1 } + + IfEntry ::= + SEQUENCE { + ifIndex + INTEGER, + ifDescr + DisplayString, + ifType + INTEGER, + ifMtu + INTEGER, + ifSpeed + Gauge, + ifPhysAddress + PhysAddress, + ifAdminStatus + INTEGER, + ifOperStatus + INTEGER, + ifLastChange + TimeTicks, + ifInOctets + Counter, + ifInUcastPkts + Counter, + ifInNUcastPkts + Counter, + ifInDiscards + Counter, + ifInErrors + Counter, + ifInUnknownProtos + Counter, + ifOutOctets + Counter, + ifOutUcastPkts + Counter, + ifOutNUcastPkts + Counter, + ifOutDiscards + Counter, + ifOutErrors + Counter, + ifOutQLen + Gauge, + ifSpecific + OBJECT IDENTIFIER + } + + ifIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "A unique value for each interface. Its value + ranges between 1 and the value of ifNumber. The + value for each interface must remain constant at + least from one re-initialization of the entity's + network management system to the next re- + initialization." + ::= { ifEntry 1 } + + ifDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A textual string containing information about the + interface. This string should include the name of + the manufacturer, the product name and the version + of the hardware interface." + ::= { ifEntry 2 } + + ifType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + regular1822(2), + hdh1822(3), + ddn-x25(4), + rfc877-x25(5), + ethernet-csmacd(6), + iso88023-csmacd(7), + iso88024-tokenBus(8), + iso88025-tokenRing(9), + iso88026-man(10), + starLan(11), + proteon-10Mbit(12), + proteon-80Mbit(13), + hyperchannel(14), + fddi(15), + lapb(16), + sdlc(17), + ds1(18), -- T-1 + e1(19), -- european equiv. of T-1 + basicISDN(20), + primaryISDN(21), -- proprietary serial + propPointToPointSerial(22), + ppp(23), + softwareLoopback(24), + eon(25), -- CLNP over IP [11] + ethernet-3Mbit(26), + + + + + + nsip(27), -- XNS over IP + slip(28), -- generic SLIP + ultra(29), -- ULTRA technologies + ds3(30), -- T-3 + sip(31), -- SMDS + frame-relay(32) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The type of interface, distinguished according to + the physical/link protocol(s) immediately `below' + the network layer in the protocol stack." + ::= { ifEntry 3 } + + ifMtu OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The size of the largest datagram which can be + sent/received on the interface, specified in + octets. For interfaces that are used for + transmitting network datagrams, this is the size + of the largest network datagram that can be sent + on the interface." + ::= { ifEntry 4 } + + ifSpeed OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An estimate of the interface's current bandwidth + in bits per second. For interfaces which do not + vary in bandwidth or for those where no accurate + estimation can be made, this object should contain + the nominal bandwidth." + ::= { ifEntry 5 } + + ifPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The interface's address at the protocol layer + immediately `below' the network layer in the + protocol stack. For interfaces which do not have + + + + + + such an address (e.g., a serial line), this object + should contain an octet string of zero length." + ::= { ifEntry 6 } + + ifAdminStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3) -- in some test mode + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The desired state of the interface. The + testing(3) state indicates that no operational + packets can be passed." + ::= { ifEntry 7 } + + ifOperStatus OBJECT-TYPE + SYNTAX INTEGER { + up(1), -- ready to pass packets + down(2), + testing(3) -- in some test mode + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The current operational state of the interface. + The testing(3) state indicates that no operational + packets can be passed." + ::= { ifEntry 8 } + + ifLastChange OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the time the interface + entered its current operational state. If the + current state was entered prior to the last re- + initialization of the local network management + subsystem, then this object contains a zero + value." + ::= { ifEntry 9 } + + ifInOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + + + + + + STATUS mandatory + DESCRIPTION + "The total number of octets received on the + interface, including framing characters." + ::= { ifEntry 10 } + + ifInUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of subnetwork-unicast packets + delivered to a higher-layer protocol." + ::= { ifEntry 11 } + + ifInNUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of non-unicast (i.e., subnetwork- + broadcast or subnetwork-multicast) packets + delivered to a higher-layer protocol." + ::= { ifEntry 12 } + + ifInDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of inbound packets which were chosen + to be discarded even though no errors had been + detected to prevent their being deliverable to a + higher-layer protocol. One possible reason for + discarding such a packet could be to free up + buffer space." + ::= { ifEntry 13 } + + ifInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of inbound packets that contained + errors preventing them from being deliverable to a + higher-layer protocol." + ::= { ifEntry 14 } + + + + + + + ifInUnknownProtos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received via the interface + which were discarded because of an unknown or + unsupported protocol." + ::= { ifEntry 15 } + + ifOutOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets transmitted out of the + interface, including framing characters." + ::= { ifEntry 16 } + + ifOutUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets that higher-level + protocols requested be transmitted to a + subnetwork-unicast address, including those that + were discarded or not sent." + ::= { ifEntry 17 } + + ifOutNUcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets that higher-level + protocols requested be transmitted to a non- + unicast (i.e., a subnetwork-broadcast or + subnetwork-multicast) address, including those + that were discarded or not sent." + ::= { ifEntry 18 } + + ifOutDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of outbound packets which were chosen + + + + + + to be discarded even though no errors had been + detected to prevent their being transmitted. One + possible reason for discarding such a packet could + be to free up buffer space." + ::= { ifEntry 19 } + + ifOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of outbound packets that could not be + transmitted because of errors." + ::= { ifEntry 20 } + + ifOutQLen OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The length of the output packet queue (in + packets)." + ::= { ifEntry 21 } + + ifSpecific OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A reference to MIB definitions specific to the + particular media being used to realize the + interface. For example, if the interface is + realized by an ethernet, then the value of this + object refers to a document defining objects + specific to ethernet. If this information is not + present, its value should be set to the OBJECT + IDENTIFIER { 0 0 }, which is a syntatically valid + object identifier, and any conformant + implementation of ASN.1 and BER must be able to + generate and recognize this value." + ::= { ifEntry 22 } + + + -- the Address Translation group + + -- Implementation of the Address Translation group is + -- mandatory for all systems. Note however that this group + -- is deprecated by MIB-II. That is, it is being included + + + + + + -- solely for compatibility with MIB-I nodes, and will most + -- likely be excluded from MIB-III nodes. From MIB-II and + -- onwards, each network protocol group contains its own + -- address translation tables. + + -- The Address Translation group contains one table which is + -- the union across all interfaces of the translation tables + -- for converting a NetworkAddress (e.g., an IP address) into + -- a subnetwork-specific address. For lack of a better term, + -- this document refers to such a subnetwork-specific address + -- as a `physical' address. + + -- Examples of such translation tables are: for broadcast + -- media where ARP is in use, the translation table is + -- equivalent to the ARP cache; or, on an X.25 network where + -- non-algorithmic translation to X.121 addresses is + -- required, the translation table contains the + -- NetworkAddress to X.121 address equivalences. + + atTable OBJECT-TYPE + SYNTAX SEQUENCE OF AtEntry + ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "The Address Translation tables contain the + NetworkAddress to `physical' address equivalences. + Some interfaces do not use translation tables for + determining address equivalences (e.g., DDN-X.25 + has an algorithmic method); if all interfaces are + of this type, then the Address Translation table + is empty, i.e., has zero entries." + ::= { at 1 } + + atEntry OBJECT-TYPE + SYNTAX AtEntry + ACCESS not-accessible + STATUS deprecated + DESCRIPTION + "Each entry contains one NetworkAddress to + `physical' address equivalence." + INDEX { atIfIndex, + atNetAddress } + ::= { atTable 1 } + + AtEntry ::= + SEQUENCE { + atIfIndex + INTEGER, + + + + + + atPhysAddress + PhysAddress, + atNetAddress + NetworkAddress + } + + atIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS deprecated + DESCRIPTION + "The interface on which this entry's equivalence + is effective. The interface identified by a + particular value of this index is the same + interface as identified by the same value of + ifIndex." + ::= { atEntry 1 } + + atPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + ACCESS read-write + STATUS deprecated + DESCRIPTION + "The media-dependent `physical' address. + + Setting this object to a null string (one of zero + length) has the effect of invaliding the + corresponding entry in the atTable object. That + is, it effectively dissasociates the interface + identified with said entry from the mapping + identified with said entry. It is an + implementation-specific matter as to whether the + agent removes an invalidated entry from the table. + Accordingly, management stations must be prepared + to receive tabular information from agents that + corresponds to entries not currently in use. + Proper interpretation of such entries requires + examination of the relevant atPhysAddress object." + ::= { atEntry 2 } + + atNetAddress OBJECT-TYPE + SYNTAX NetworkAddress + ACCESS read-write + STATUS deprecated + DESCRIPTION + "The NetworkAddress (e.g., the IP address) + corresponding to the media-dependent `physical' + address." + + + + + + ::= { atEntry 3 } + + + -- the IP group + + -- Implementation of the IP group is mandatory for all + -- systems. + + ipForwarding OBJECT-TYPE + SYNTAX INTEGER { + forwarding(1), -- acting as a gateway + not-forwarding(2) -- NOT acting as a gateway + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The indication of whether this entity is acting + as an IP gateway in respect to the forwarding of + datagrams received by, but not addressed to, this + entity. IP gateways forward datagrams. IP hosts + do not (except those source-routed via the host). + + Note that for some managed nodes, this object may + take on only a subset of the values possible. + Accordingly, it is appropriate for an agent to + return a `badValue' response if a management + station attempts to change this object to an + inappropriate value." + ::= { ip 1 } + + ipDefaultTTL OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The default value inserted into the Time-To-Live + field of the IP header of datagrams originated at + this entity, whenever a TTL value is not supplied + by the transport layer protocol." + ::= { ip 2 } + + ipInReceives OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of input datagrams received from + interfaces, including those received in error." + + + + + + ::= { ip 3 } + + ipInHdrErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input datagrams discarded due to + errors in their IP headers, including bad + checksums, version number mismatch, other format + errors, time-to-live exceeded, errors discovered + in processing their IP options, etc." + ::= { ip 4 } + + ipInAddrErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input datagrams discarded because + the IP address in their IP header's destination + field was not a valid address to be received at + this entity. This count includes invalid + addresses (e.g., 0.0.0.0) and addresses of + unsupported Classes (e.g., Class E). For entities + which are not IP Gateways and therefore do not + forward datagrams, this counter includes datagrams + discarded because the destination address was not + a local address." + ::= { ip 5 } + + ipForwDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input datagrams for which this + entity was not their final IP destination, as a + result of which an attempt was made to find a + route to forward them to that final destination. + In entities which do not act as IP Gateways, this + counter will include only those packets which were + Source-Routed via this entity, and the Source- + Route option processing was successful." + ::= { ip 6 } + + ipInUnknownProtos OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally-addressed datagrams + received successfully but discarded because of an + unknown or unsupported protocol." + ::= { ip 7 } + + ipInDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of input IP datagrams for which no + problems were encountered to prevent their + continued processing, but which were discarded + (e.g., for lack of buffer space). Note that this + counter does not include any datagrams discarded + while awaiting re-assembly." + ::= { ip 8 } + + ipInDelivers OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of input datagrams successfully + delivered to IP user-protocols (including ICMP)." + ::= { ip 9 } + + ipOutRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of IP datagrams which local IP + user-protocols (including ICMP) supplied to IP in + requests for transmission. Note that this counter + does not include any datagrams counted in + ipForwDatagrams." + ::= { ip 10 } + + ipOutDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of output IP datagrams for which no + + + + + + problem was encountered to prevent their + transmission to their destination, but which were + discarded (e.g., for lack of buffer space). Note + that this counter would include datagrams counted + in ipForwDatagrams if any such packets met this + (discretionary) discard criterion." + ::= { ip 11 } + + ipOutNoRoutes OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams discarded because no + route could be found to transmit them to their + destination. Note that this counter includes any + packets counted in ipForwDatagrams which meet this + `no-route' criterion. Note that this includes any + datagarms which a host cannot route because all of + its default gateways are down." + ::= { ip 12 } + + ipReasmTimeout OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum number of seconds which received + fragments are held while they are awaiting + reassembly at this entity." + ::= { ip 13 } + + ipReasmReqds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP fragments received which needed + to be reassembled at this entity." + ::= { ip 14 } + + ipReasmOKs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams successfully re- + assembled." + + + + + + ::= { ip 15 } + + ipReasmFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of failures detected by the IP re- + assembly algorithm (for whatever reason: timed + out, errors, etc). Note that this is not + necessarily a count of discarded IP fragments + since some algorithms (notably the algorithm in + RFC 815) can lose track of the number of fragments + by combining them as they are received." + ::= { ip 16 } + + ipFragOKs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams that have been + successfully fragmented at this entity." + ::= { ip 17 } + + ipFragFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagrams that have been + discarded because they needed to be fragmented at + this entity but could not be, e.g., because their + Don't Fragment flag was set." + ::= { ip 18 } + + ipFragCreates OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of IP datagram fragments that have + been generated as a result of fragmentation at + this entity." + ::= { ip 19 } + + + + + + + + + -- the IP address table + + -- The IP address table contains this entity's IP addressing + -- information. + + ipAddrTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpAddrEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The table of addressing information relevant to + this entity's IP addresses." + ::= { ip 20 } + + ipAddrEntry OBJECT-TYPE + SYNTAX IpAddrEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The addressing information for one of this + entity's IP addresses." + INDEX { ipAdEntAddr } + ::= { ipAddrTable 1 } + + IpAddrEntry ::= + SEQUENCE { + ipAdEntAddr + IpAddress, + ipAdEntIfIndex + INTEGER, + ipAdEntNetMask + IpAddress, + ipAdEntBcastAddr + INTEGER, + ipAdEntReasmMaxSize + INTEGER (0..65535) + } + + ipAdEntAddr OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The IP address to which this entry's addressing + information pertains." + ::= { ipAddrEntry 1 } + + + + + + + + ipAdEntIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The index value which uniquely identifies the + interface to which this entry is applicable. The + interface identified by a particular value of this + index is the same interface as identified by the + same value of ifIndex." + ::= { ipAddrEntry 2 } + + ipAdEntNetMask OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The subnet mask associated with the IP address of + this entry. The value of the mask is an IP + address with all the network bits set to 1 and all + the hosts bits set to 0." + ::= { ipAddrEntry 3 } + + ipAdEntBcastAddr OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of the least-significant bit in the IP + broadcast address used for sending datagrams on + the (logical) interface associated with the IP + address of this entry. For example, when the + Internet standard all-ones broadcast address is + used, the value will be 1. This value applies to + both the subnet and network broadcasts addresses + used by the entity on this (logical) interface." + ::= { ipAddrEntry 4 } + + ipAdEntReasmMaxSize OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The size of the largest IP datagram which this + entity can re-assemble from incoming IP fragmented + datagrams received on this interface." + ::= { ipAddrEntry 5 } + + + + + + + -- the IP routing table + + -- The IP routing table contains an entry for each route + -- presently known to this entity. + + ipRouteTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpRouteEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "This entity's IP Routing table." + ::= { ip 21 } + + ipRouteEntry OBJECT-TYPE + SYNTAX IpRouteEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A route to a particular destination." + INDEX { ipRouteDest } + ::= { ipRouteTable 1 } + + IpRouteEntry ::= + SEQUENCE { + ipRouteDest + IpAddress, + ipRouteIfIndex + INTEGER, + ipRouteMetric1 + INTEGER, + ipRouteMetric2 + INTEGER, + ipRouteMetric3 + INTEGER, + ipRouteMetric4 + INTEGER, + ipRouteNextHop + IpAddress, + ipRouteType + INTEGER, + ipRouteProto + INTEGER, + ipRouteAge + INTEGER, + ipRouteMask + IpAddress, + ipRouteMetric5 + INTEGER, + + + + + + ipRouteInfo + OBJECT IDENTIFIER + } + + ipRouteDest OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The destination IP address of this route. An + entry with a value of 0.0.0.0 is considered a + default route. Multiple routes to a single + destination can appear in the table, but access to + such multiple entries is dependent on the table- + access mechanisms defined by the network + management protocol in use." + ::= { ipRouteEntry 1 } + + ipRouteIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The index value which uniquely identifies the + local interface through which the next hop of this + route should be reached. The interface identified + by a particular value of this index is the same + interface as identified by the same value of + ifIndex." + ::= { ipRouteEntry 2 } + + ipRouteMetric1 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The primary routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 3 } + + ipRouteMetric2 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + + + + + + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 4 } + + ipRouteMetric3 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 5 } + + ipRouteMetric4 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 6 } + + ipRouteNextHop OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The IP address of the next hop of this route. + (In the case of a route bound to an interface + which is realized via a broadcast media, the value + of this field is the agent's IP address on that + interface.)" + ::= { ipRouteEntry 7 } + + ipRouteType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + invalid(2), -- an invalidated route + + + + + + -- route to directly + direct(3), -- connected (sub-)network + + -- route to a non-local + indirect(4) -- host/network/sub-network + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The type of route. Note that the values + direct(3) and indirect(4) refer to the notion of + direct and indirect routing in the IP + architecture. + + Setting this object to the value invalid(2) has + the effect of invalidating the corresponding entry + in the ipRouteTable object. That is, it + effectively dissasociates the destination + identified with said entry from the route + identified with said entry. It is an + implementation-specific matter as to whether the + agent removes an invalidated entry from the table. + Accordingly, management stations must be prepared + to receive tabular information from agents that + corresponds to entries not currently in use. + Proper interpretation of such entries requires + examination of the relevant ipRouteType object." + ::= { ipRouteEntry 8 } + + ipRouteProto OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + -- non-protocol information, + -- e.g., manually configured + local(2), -- entries + + -- set via a network + netmgmt(3), -- management protocol + + -- obtained via ICMP, + icmp(4), -- e.g., Redirect + + -- the remaining values are + -- all gateway routing + -- protocols + egp(5), + ggp(6), + + + + + + hello(7), + rip(8), + is-is(9), + es-is(10), + ciscoIgrp(11), + bbnSpfIgp(12), + ospf(13), + bgp(14) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The routing mechanism via which this route was + learned. Inclusion of values for gateway routing + protocols is not intended to imply that hosts + should support those protocols." + ::= { ipRouteEntry 9 } + + ipRouteAge OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The number of seconds since this route was last + updated or otherwise determined to be correct. + Note that no semantics of `too old' can be implied + except through knowledge of the routing protocol + by which the route was learned." + ::= { ipRouteEntry 10 } + + ipRouteMask OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Indicate the mask to be logical-ANDed with the + destination address before being compared to the + value in the ipRouteDest field. For those systems + that do not support arbitrary subnet masks, an + agent constructs the value of the ipRouteMask by + determining whether the value of the correspondent + ipRouteDest field belong to a class-A, B, or C + network, and then using one of: + + mask network + 255.0.0.0 class-A + 255.255.0.0 class-B + 255.255.255.0 class-C + + + + + + If the value of the ipRouteDest is 0.0.0.0 (a + default route), then the mask value is also + 0.0.0.0. It should be noted that all IP routing + subsystems implicitly use this mechanism." + ::= { ipRouteEntry 11 } + + ipRouteMetric5 OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An alternate routing metric for this route. The + semantics of this metric are determined by the + routing-protocol specified in the route's + ipRouteProto value. If this metric is not used, + its value should be set to -1." + ::= { ipRouteEntry 12 } + + ipRouteInfo OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A reference to MIB definitions specific to the + particular routing protocol which is responsible + for this route, as determined by the value + specified in the route's ipRouteProto value. If + this information is not present, its value should + be set to the OBJECT IDENTIFIER { 0 0 }, which is + a syntatically valid object identifier, and any + conformant implementation of ASN.1 and BER must be + able to generate and recognize this value." + ::= { ipRouteEntry 13 } + + + -- the IP Address Translation table + + -- The IP address translation table contain the IpAddress to + -- `physical' address equivalences. Some interfaces do not + -- use translation tables for determining address + -- equivalences (e.g., DDN-X.25 has an algorithmic method); + -- if all interfaces are of this type, then the Address + -- Translation table is empty, i.e., has zero entries. + + ipNetToMediaTable OBJECT-TYPE + SYNTAX SEQUENCE OF IpNetToMediaEntry + ACCESS not-accessible + STATUS mandatory + + + + + + DESCRIPTION + "The IP Address Translation table used for mapping + from IP addresses to physical addresses." + ::= { ip 22 } + + ipNetToMediaEntry OBJECT-TYPE + SYNTAX IpNetToMediaEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Each entry contains one IpAddress to `physical' + address equivalence." + INDEX { ipNetToMediaIfIndex, + ipNetToMediaNetAddress } + ::= { ipNetToMediaTable 1 } + + IpNetToMediaEntry ::= + SEQUENCE { + ipNetToMediaIfIndex + INTEGER, + ipNetToMediaPhysAddress + PhysAddress, + ipNetToMediaNetAddress + IpAddress, + ipNetToMediaType + INTEGER + } + + ipNetToMediaIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The interface on which this entry's equivalence + is effective. The interface identified by a + particular value of this index is the same + interface as identified by the same value of + ifIndex." + ::= { ipNetToMediaEntry 1 } + + ipNetToMediaPhysAddress OBJECT-TYPE + SYNTAX PhysAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The media-dependent `physical' address." + ::= { ipNetToMediaEntry 2 } + + + + + + + ipNetToMediaNetAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The IpAddress corresponding to the media- + dependent `physical' address." + ::= { ipNetToMediaEntry 3 } + + ipNetToMediaType OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + invalid(2), -- an invalidated mapping + dynamic(3), + static(4) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The type of mapping. + + Setting this object to the value invalid(2) has + the effect of invalidating the corresponding entry + in the ipNetToMediaTable. That is, it effectively + dissasociates the interface identified with said + entry from the mapping identified with said entry. + It is an implementation-specific matter as to + whether the agent removes an invalidated entry + from the table. Accordingly, management stations + must be prepared to receive tabular information + from agents that corresponds to entries not + currently in use. Proper interpretation of such + entries requires examination of the relevant + ipNetToMediaType object." + ::= { ipNetToMediaEntry 4 } + + + -- additional IP objects + + ipRoutingDiscards OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of routing entries which were chosen + to be discarded even though they are valid. One + possible reason for discarding such an entry could + be to free-up buffer space for other routing + + + + + + entries." + ::= { ip 23 } + + + -- the ICMP group + + -- Implementation of the ICMP group is mandatory for all + -- systems. + + icmpInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ICMP messages which the + entity received. Note that this counter includes + all those counted by icmpInErrors." + ::= { icmp 1 } + + icmpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP messages which the entity + received but determined as having ICMP-specific + errors (bad ICMP checksums, bad length, etc.)." + ::= { icmp 2 } + + icmpInDestUnreachs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Destination Unreachable + messages received." + ::= { icmp 3 } + + icmpInTimeExcds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Time Exceeded messages + received." + ::= { icmp 4 } + + + + + + + + icmpInParmProbs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Parameter Problem messages + received." + ::= { icmp 5 } + + icmpInSrcQuenchs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Source Quench messages + received." + ::= { icmp 6 } + + icmpInRedirects OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Redirect messages received." + ::= { icmp 7 } + + icmpInEchos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo (request) messages + received." + ::= { icmp 8 } + + icmpInEchoReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo Reply messages received." + ::= { icmp 9 } + + icmpInTimestamps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + + + + + + "The number of ICMP Timestamp (request) messages + received." + ::= { icmp 10 } + + icmpInTimestampReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp Reply messages + received." + ::= { icmp 11 } + + icmpInAddrMasks OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Request messages + received." + ::= { icmp 12 } + + icmpInAddrMaskReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Reply messages + received." + ::= { icmp 13 } + + icmpOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ICMP messages which this + entity attempted to send. Note that this counter + includes all those counted by icmpOutErrors." + ::= { icmp 14 } + + icmpOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP messages which this entity did + not send due to problems discovered within ICMP + + + + + + such as a lack of buffers. This value should not + include errors discovered outside the ICMP layer + such as the inability of IP to route the resultant + datagram. In some implementations there may be no + types of error which contribute to this counter's + value." + ::= { icmp 15 } + + icmpOutDestUnreachs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Destination Unreachable + messages sent." + ::= { icmp 16 } + + icmpOutTimeExcds OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Time Exceeded messages sent." + ::= { icmp 17 } + + icmpOutParmProbs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Parameter Problem messages + sent." + ::= { icmp 18 } + + icmpOutSrcQuenchs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Source Quench messages sent." + ::= { icmp 19 } + + icmpOutRedirects OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Redirect messages sent. For a + + + + + + host, this object will always be zero, since hosts + do not send redirects." + ::= { icmp 20 } + + icmpOutEchos OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo (request) messages sent." + ::= { icmp 21 } + + icmpOutEchoReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Echo Reply messages sent." + ::= { icmp 22 } + + icmpOutTimestamps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp (request) messages + sent." + ::= { icmp 23 } + + icmpOutTimestampReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Timestamp Reply messages + sent." + ::= { icmp 24 } + + icmpOutAddrMasks OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Request messages + sent." + ::= { icmp 25 } + + + + + + + + icmpOutAddrMaskReps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ICMP Address Mask Reply messages + sent." + ::= { icmp 26 } + + + -- the TCP group + + -- Implementation of the TCP group is mandatory for all + -- systems that implement the TCP. + + -- Note that instances of object types that represent + -- information about a particular TCP connection are + -- transient; they persist only as long as the connection + -- in question. + + tcpRtoAlgorithm OBJECT-TYPE + SYNTAX INTEGER { + other(1), -- none of the following + + constant(2), -- a constant rto + rsre(3), -- MIL-STD-1778, Appendix B + vanj(4) -- Van Jacobson's algorithm [10] + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The algorithm used to determine the timeout value + used for retransmitting unacknowledged octets." + ::= { tcp 1 } + + tcpRtoMin OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The minimum value permitted by a TCP + implementation for the retransmission timeout, + measured in milliseconds. More refined semantics + for objects of this type depend upon the algorithm + used to determine the retransmission timeout. In + particular, when the timeout algorithm is rsre(3), + an object of this type has the semantics of the + LBOUND quantity described in RFC 793." + + + + + + ::= { tcp 2 } + + + tcpRtoMax OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum value permitted by a TCP + implementation for the retransmission timeout, + measured in milliseconds. More refined semantics + for objects of this type depend upon the algorithm + used to determine the retransmission timeout. In + particular, when the timeout algorithm is rsre(3), + an object of this type has the semantics of the + UBOUND quantity described in RFC 793." + ::= { tcp 3 } + + tcpMaxConn OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The limit on the total number of TCP connections + the entity can support. In entities where the + maximum number of connections is dynamic, this + object should contain the value -1." + ::= { tcp 4 } + + tcpActiveOpens OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the SYN-SENT state from the + CLOSED state." + ::= { tcp 5 } + + tcpPassiveOpens OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the SYN-RCVD state from the + LISTEN state." + ::= { tcp 6 } + + + + + + tcpAttemptFails OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the CLOSED state from either + the SYN-SENT state or the SYN-RCVD state, plus the + number of times TCP connections have made a direct + transition to the LISTEN state from the SYN-RCVD + state." + ::= { tcp 7 } + + tcpEstabResets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times TCP connections have made a + direct transition to the CLOSED state from either + the ESTABLISHED state or the CLOSE-WAIT state." + ::= { tcp 8 } + + tcpCurrEstab OBJECT-TYPE + SYNTAX Gauge + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of TCP connections for which the + current state is either ESTABLISHED or CLOSE- + WAIT." + ::= { tcp 9 } + + tcpInSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of segments received, including + those received in error. This count includes + segments received on currently established + connections." + ::= { tcp 10 } + + tcpOutSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The total number of segments sent, including + those on current connections but excluding those + containing only retransmitted octets." + ::= { tcp 11 } + + tcpRetransSegs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of segments retransmitted - that + is, the number of TCP segments transmitted + containing one or more previously transmitted + octets." + ::= { tcp 12 } + + + -- the TCP Connection table + + -- The TCP connection table contains information about this + -- entity's existing TCP connections. + + tcpConnTable OBJECT-TYPE + SYNTAX SEQUENCE OF TcpConnEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A table containing TCP connection-specific + information." + ::= { tcp 13 } + + tcpConnEntry OBJECT-TYPE + SYNTAX TcpConnEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about a particular current TCP + connection. An object of this type is transient, + in that it ceases to exist when (or soon after) + the connection makes the transition to the CLOSED + state." + INDEX { tcpConnLocalAddress, + tcpConnLocalPort, + tcpConnRemAddress, + tcpConnRemPort } + ::= { tcpConnTable 1 } + + + + + + + TcpConnEntry ::= + SEQUENCE { + tcpConnState + INTEGER, + tcpConnLocalAddress + IpAddress, + tcpConnLocalPort + INTEGER (0..65535), + tcpConnRemAddress + IpAddress, + tcpConnRemPort + INTEGER (0..65535) + } + + tcpConnState OBJECT-TYPE + SYNTAX INTEGER { + closed(1), + listen(2), + synSent(3), + synReceived(4), + established(5), + finWait1(6), + finWait2(7), + closeWait(8), + lastAck(9), + closing(10), + timeWait(11), + deleteTCB(12) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The state of this TCP connection. + + The only value which may be set by a management + station is deleteTCB(12). Accordingly, it is + appropriate for an agent to return a `badValue' + response if a management station attempts to set + this object to any other value. + + If a management station sets this object to the + value deleteTCB(12), then this has the effect of + deleting the TCB (as defined in RFC 793) of the + corresponding connection on the managed node, + resulting in immediate termination of the + connection. + + As an implementation-specific option, a RST + + + + + + segment may be sent from the managed node to the + other TCP endpoint (note however that RST segments + are not sent reliably)." + ::= { tcpConnEntry 1 } + + tcpConnLocalAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local IP address for this TCP connection. In + the case of a connection in the listen state which + is willing to accept connections for any IP + interface associated with the node, the value + 0.0.0.0 is used." + ::= { tcpConnEntry 2 } + + tcpConnLocalPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local port number for this TCP connection." + ::= { tcpConnEntry 3 } + + tcpConnRemAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The remote IP address for this TCP connection." + ::= { tcpConnEntry 4 } + + tcpConnRemPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The remote port number for this TCP connection." + ::= { tcpConnEntry 5 } + + + -- additional TCP objects + + tcpInErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The total number of segments received in error + (e.g., bad TCP checksums)." + ::= { tcp 14 } + + tcpOutRsts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of TCP segments sent containing the + RST flag." + ::= { tcp 15 } + + + -- the UDP group + + -- Implementation of the UDP group is mandatory for all + -- systems which implement the UDP. + + udpInDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of UDP datagrams delivered to + UDP users." + ::= { udp 1 } + + udpNoPorts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of received UDP datagrams for + which there was no application at the destination + port." + ::= { udp 2 } + + udpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of received UDP datagrams that could + not be delivered for reasons other than the lack + of an application at the destination port." + ::= { udp 3 } + + + + + + udpOutDatagrams OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of UDP datagrams sent from this + entity." + ::= { udp 4 } + + + -- the UDP Listener table + + -- The UDP listener table contains information about this + -- entity's UDP end-points on which a local application is + -- currently accepting datagrams. + + udpTable OBJECT-TYPE + SYNTAX SEQUENCE OF UdpEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A table containing UDP listener information." + ::= { udp 5 } + + udpEntry OBJECT-TYPE + SYNTAX UdpEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about a particular current UDP + listener." + INDEX { udpLocalAddress, udpLocalPort } + ::= { udpTable 1 } + + UdpEntry ::= + SEQUENCE { + udpLocalAddress + IpAddress, + udpLocalPort + INTEGER (0..65535) + } + + udpLocalAddress OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local IP address for this UDP listener. In + + + + + + the case of a UDP listener which is willing to + accept datagrams for any IP interface associated + with the node, the value 0.0.0.0 is used." + ::= { udpEntry 1 } + + udpLocalPort OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The local port number for this UDP listener." + ::= { udpEntry 2 } + + + -- the EGP group + + -- Implementation of the EGP group is mandatory for all + -- systems which implement the EGP. + + egpInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received without + error." + ::= { egp 1 } + + egpInErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received that proved + to be in error." + ::= { egp 2 } + + egpOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of locally generated EGP + messages." + ::= { egp 3 } + + egpOutErrors OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally generated EGP messages not + sent due to resource limitations within an EGP + entity." + ::= { egp 4 } + + + -- the EGP Neighbor table + + -- The EGP neighbor table contains information about this + -- entity's EGP neighbors. + + egpNeighTable OBJECT-TYPE + SYNTAX SEQUENCE OF EgpNeighEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "The EGP neighbor table." + ::= { egp 5 } + + egpNeighEntry OBJECT-TYPE + SYNTAX EgpNeighEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about this entity's relationship with + a particular EGP neighbor." + INDEX { egpNeighAddr } + ::= { egpNeighTable 1 } + + EgpNeighEntry ::= + SEQUENCE { + egpNeighState + INTEGER, + egpNeighAddr + IpAddress, + egpNeighAs + INTEGER, + egpNeighInMsgs + Counter, + egpNeighInErrs + Counter, + egpNeighOutMsgs + Counter, + egpNeighOutErrs + Counter, + + + + + + egpNeighInErrMsgs + Counter, + egpNeighOutErrMsgs + Counter, + egpNeighStateUps + Counter, + egpNeighStateDowns + Counter, + egpNeighIntervalHello + INTEGER, + egpNeighIntervalPoll + INTEGER, + egpNeighMode + INTEGER, + egpNeighEventTrigger + INTEGER + } + + egpNeighState OBJECT-TYPE + SYNTAX INTEGER { + idle(1), + acquisition(2), + down(3), + up(4), + cease(5) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The EGP state of the local system with respect to + this entry's EGP neighbor. Each EGP state is + represented by a value that is one greater than + the numerical value associated with said state in + RFC 904." + ::= { egpNeighEntry 1 } + + egpNeighAddr OBJECT-TYPE + SYNTAX IpAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The IP address of this entry's EGP neighbor." + ::= { egpNeighEntry 2 } + + egpNeighAs OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The autonomous system of this EGP peer. Zero + should be specified if the autonomous system + number of the neighbor is not yet known." + ::= { egpNeighEntry 3 } + + egpNeighInMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received without error + from this EGP peer." + ::= { egpNeighEntry 4 } + + egpNeighInErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP messages received from this EGP + peer that proved to be in error (e.g., bad EGP + checksum)." + ::= { egpNeighEntry 5 } + + egpNeighOutMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally generated EGP messages to + this EGP peer." + ::= { egpNeighEntry 6 } + + egpNeighOutErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of locally generated EGP messages not + sent to this EGP peer due to resource limitations + within an EGP entity." + ::= { egpNeighEntry 7 } + + egpNeighInErrMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The number of EGP-defined error messages received + from this EGP peer." + ::= { egpNeighEntry 8 } + + egpNeighOutErrMsgs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP-defined error messages sent to + this EGP peer." + ::= { egpNeighEntry 9 } + + egpNeighStateUps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP state transitions to the UP + state with this EGP peer." + ::= { egpNeighEntry 10 } + + egpNeighStateDowns OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of EGP state transitions from the UP + state to any other state with this EGP peer." + ::= { egpNeighEntry 11 } + + egpNeighIntervalHello OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The interval between EGP Hello command + retransmissions (in hundredths of a second). This + represents the t1 timer as defined in RFC 904." + ::= { egpNeighEntry 12 } + + egpNeighIntervalPoll OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The interval between EGP poll command + + + + + + retransmissions (in hundredths of a second). This + represents the t3 timer as defined in RFC 904." + ::= { egpNeighEntry 13 } + + egpNeighMode OBJECT-TYPE + SYNTAX INTEGER { active(1), passive(2) } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The polling mode of this EGP entity, either + passive or active." + ::= { egpNeighEntry 14 } + + egpNeighEventTrigger OBJECT-TYPE + SYNTAX INTEGER { start(1), stop(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A control variable used to trigger operator- + initiated Start and Stop events. When read, this + variable always returns the most recent value that + egpNeighEventTrigger was set to. If it has not + been set since the last initialization of the + network management subsystem on the node, it + returns a value of `stop'. + + When set, this variable causes a Start or Stop + event on the specified neighbor, as specified on + pages 8-10 of RFC 904. Briefly, a Start event + causes an Idle peer to begin neighbor acquisition + and a non-Idle peer to reinitiate neighbor + acquisition. A stop event causes a non-Idle peer + to return to the Idle state until a Start event + occurs, either via egpNeighEventTrigger or + otherwise." + ::= { egpNeighEntry 15 } + + + -- additional EGP objects + + egpAs OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The autonomous system number of this EGP entity." + ::= { egp 6 } + + + + + + + -- the Transmission group + + -- Based on the transmission media underlying each interface + -- on a system, the corresponding portion of the Transmission + -- group is mandatory for that system. + + -- When Internet-standard definitions for managing + -- transmission media are defined, the transmission group is + -- used to provide a prefix for the names of those objects. + + -- Typically, such definitions reside in the experimental + -- portion of the MIB until they are "proven", then as a + -- part of the Internet standardization process, the + -- definitions are accordingly elevated and a new object + -- identifier, under the transmission group is defined. By + -- convention, the name assigned is: + -- + -- type OBJECT IDENTIFIER ::= { transmission number } + -- + -- where "type" is the symbolic value used for the media in + -- the ifType column of the ifTable object, and "number" is + -- the actual integer value corresponding to the symbol. + + + -- the SNMP group + + -- Implementation of the SNMP group is mandatory for all + -- systems which support an SNMP protocol entity. Some of + -- the objects defined below will be zero-valued in those + -- SNMP implementations that are optimized to support only + -- those functions specific to either a management agent or + -- a management station. In particular, it should be + -- observed that the objects below refer to an SNMP entity, + -- and there may be several SNMP entities residing on a + -- managed node (e.g., if the node is hosting acting as + -- a management station). + + snmpInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of Messages delivered to the + SNMP entity from the transport service." + ::= { snmp 1 } + + snmpOutPkts OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + passed from the SNMP protocol entity to the + transport service." + ::= { snmp 2 } + + snmpInBadVersions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + delivered to the SNMP protocol entity and were for + an unsupported SNMP version." + ::= { snmp 3 } + + snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which used a SNMP + community name not known to said entity." + ::= { snmp 4 } + + snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which represented an SNMP + operation which was not allowed by the SNMP + community named in the Message." + ::= { snmp 5 } + + snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ASN.1 or BER errors + encountered by the SNMP protocol entity when + decoding received SNMP Messages." + ::= { snmp 6 } + + + + + + -- { snmp 7 } is not used + + snmpInTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `tooBig'." + ::= { snmp 8 } + + snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `noSuchName'." + ::= { snmp 9 } + + snmpInBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 10 } + + snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number valid SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `readOnly'. It should be noted that it is a + protocol error to generate an SNMP PDU which + contains the value `readOnly' in the error-status + field, as such this object is provided as a means + of detecting incorrect implementations of the + + + + + + SNMP." + ::= { snmp 11 } + + snmpInGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 12 } + + snmpInTotalReqVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + retrieved successfully by the SNMP protocol entity + as the result of receiving valid SNMP Get-Request + and Get-Next PDUs." + ::= { snmp 13 } + + snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + altered successfully by the SNMP protocol entity + as the result of receiving valid SNMP Set-Request + PDUs." + ::= { snmp 14 } + + snmpInGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 15 } + + snmpInGetNexts OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 16 } + + snmpInSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 17 } + + snmpInGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 18 } + + snmpInTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 19 } + + snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `tooBig.'" + ::= { snmp 20 } + + + + + + snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status is + `noSuchName'." + ::= { snmp 21 } + + snmpOutBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 22 } + + -- { snmp 23 } is not used + + snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 24 } + + snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 25 } + + snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 26 } + + snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 27 } + + snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 28 } + + snmpOutTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 29 } + + snmpEnableAuthenTraps OBJECT-TYPE + SYNTAX INTEGER { enabled(1), disabled(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Indicates whether the SNMP agent process is + permitted to generate authentication-failure + traps. The value of this object overrides any + configuration information; as such, it provides a + means whereby all authentication-failure traps may + be disabled. + + Note that it is strongly recommended that this + object be stored in non-volatile memory so that it + remains constant between re-initializations of the + network management system." + + + + + + ::= { snmp 30 } + + END + diff --git a/lib/snmp/test/test-mibs/RFC1271-MIB.mib b/lib/snmp/test/test-mibs/RFC1271-MIB.mib new file mode 100644 index 0000000000..25778dede8 --- /dev/null +++ b/lib/snmp/test/test-mibs/RFC1271-MIB.mib @@ -0,0 +1,3492 @@ + RFC1271-MIB DEFINITIONS ::= BEGIN + + IMPORTS + Counter FROM RFC1155-SMI + mib-2,DisplayString FROM RFC1213-MIB + OBJECT-TYPE FROM RFC-1212; + + -- This MIB module uses the extended OBJECT-TYPE macro as + -- defined in [9]. + + + -- Remote Network Monitoring MIB + + rmon OBJECT IDENTIFIER ::= { mib-2 16 } + + + -- textual conventions + + OwnerString ::= DisplayString + -- This data type is used to model an administratively + -- assigned name of the owner of a resource. This + -- information is taken from the NVT ASCII character set. + -- It is suggested that this name contain one or more + -- of the following: + -- IP address, management station name, network manager's + -- name, location, or phone number. + -- In some cases the agent itself will be the owner of + -- an entry. In these cases, this string shall be set + -- to a string starting with 'monitor'. + + + -- + -- SNMP access control is articulated entirely in terms of + -- the contents of MIB views; access to a particular SNMP + -- object instance depends only upon its presence or + -- absence in a particular MIB view and never upon its + -- value or the value of related object instances. Thus, + -- objects of this type afford resolution of resource + -- contention only among cooperating managers; they + -- realize no access control function with respect + -- to uncooperative parties. + -- + -- By convention, objects with this syntax are declared + -- as having + -- + -- SIZE (0..127) + + + EntryStatus ::= INTEGER + { valid(1), + createRequest(2), + underCreation(3), + invalid(4) + } + + -- The status of a table entry. + -- + -- Setting this object to the value invalid(4) has the + -- effect of invalidating the corresponding entry. + -- That is, it effectively disassociates the mapping + -- identified with said entry. + -- It is an implementation-specific matter as to whether + -- the agent removes an invalidated entry from the table. + -- Accordingly, management stations must be prepared to + -- receive tabular information from agents that corresponds + -- to entries currently not in use. Proper + -- interpretation of such entries requires examination + -- of the relevant EntryStatus object. + -- + -- An existing instance of this object cannot be set to + -- createRequest(2). This object may only be set to + -- createRequest(2) when this instance is created. When + -- this object is created, the agent may wish to create + -- supplemental object instances to complete a conceptual + -- row in this table. Immediately after completing the + -- create operation, the agent must set this object to + -- underCreation(3). + -- + -- Entries shall exist in the underCreation(3) state until + + + -- the management station is finished configuring the + -- entry and sets this object to valid(1) or aborts, + -- setting this object to invalid(4). If the agent + -- determines that an entry has been in the + -- underCreation(3) state for an abnormally long time, + -- it may decide that the management station has + -- crashed. If the agent makes this decision, + -- it may set this object to invalid(4) to reclaim the + -- entry. A prudent agent will understand that the + -- management station may need to wait for human input + -- and will allow for that possibility in its + -- determination of this abnormally long period. + + + statistics OBJECT IDENTIFIER ::= { rmon 1 } + history OBJECT IDENTIFIER ::= { rmon 2 } + alarm OBJECT IDENTIFIER ::= { rmon 3 } + hosts OBJECT IDENTIFIER ::= { rmon 4 } + hostTopN OBJECT IDENTIFIER ::= { rmon 5 } + matrix OBJECT IDENTIFIER ::= { rmon 6 } + filter OBJECT IDENTIFIER ::= { rmon 7 } + capture OBJECT IDENTIFIER ::= { rmon 8 } + event OBJECT IDENTIFIER ::= { rmon 9 } + + + -- The Statistics Group + -- + -- Implementation of the Statistics group is optional. + -- + -- The statistics group contains statistics measured by the + -- probe for each monitored interface on this device. These + -- statistics take the form of free running counters that + -- start from zero when a valid entry is created. + -- + -- This group currently has statistics defined only for + -- Ethernet interfaces. Each etherStatsEntry contains + -- statistics for one Ethernet interface. The probe must + -- create one etherStats entry for each monitored Ethernet + -- interface on the device. + + etherStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF EtherStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of Ethernet statistics entries." + ::= { statistics 1 } + + + + etherStatsEntry OBJECT-TYPE + SYNTAX EtherStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics kept for a particular + Ethernet interface." + INDEX { etherStatsIndex } + ::= { etherStatsTable 1 } + + EtherStatsEntry ::= SEQUENCE { + etherStatsIndex INTEGER (1..65535), + etherStatsDataSource OBJECT IDENTIFIER, + etherStatsDropEvents Counter, + etherStatsOctets Counter, + etherStatsPkts Counter, + etherStatsBroadcastPkts Counter, + etherStatsMulticastPkts Counter, + etherStatsCRCAlignErrors Counter, + etherStatsUndersizePkts Counter, + etherStatsOversizePkts Counter, + etherStatsFragments Counter, + etherStatsJabbers Counter, + etherStatsCollisions Counter, + etherStatsPkts64Octets Counter, + etherStatsPkts65to127Octets Counter, + etherStatsPkts128to255Octets Counter, + etherStatsPkts256to511Octets Counter, + etherStatsPkts512to1023Octets Counter, + etherStatsPkts1024to1518Octets Counter, + etherStatsOwner OwnerString, + etherStatsStatus INTEGER + } + + etherStatsIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies this + etherStats entry." + ::= { etherStatsEntry 1 } + + etherStatsDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + + + "This object identifies the source of the data that + this etherStats entry is configured to analyze. This + source can be any ethernet interface on this device. + In order to identify a particular interface, this + object shall identify the instance of the ifIndex + object, defined in [4,6], for the desired interface. + For example, if an entry were to receive data from + interface #1, this object would be set to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the + identified interface. + + This object may not be modified if the associated + etherStatsStatus object is equal to valid(1)." + ::= { etherStatsEntry 2 } + + etherStatsDropEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of events in which packets + were dropped by the probe due to lack of resources. + Note that this number is not necessarily the number of + packets dropped; it is just the number of times this + condition has been detected." + ::= { etherStatsEntry 3 } + + etherStatsOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets of data (including + those in bad packets) received on the + network (excluding framing bits but including + FCS octets)." + ::= { etherStatsEntry 4 } + + etherStatsPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including error packets) + received." + ::= { etherStatsEntry 5 } + + + etherStatsBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good packets received that were + directed to the broadcast address." + ::= { etherStatsEntry 6 } + + etherStatsMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good packets received that were + directed to a multicast address. Note that this + number does not include packets directed to the + broadcast address." + ::= { etherStatsEntry 7 } + + etherStatsCRCAlignErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received that + had a length (excluding framing bits, but + including FCS octets) of between 64 and 1518 + octets, inclusive, but were not an integral number + of octets in length or had a bad Frame Check + Sequence (FCS)." + ::= { etherStatsEntry 8 } + + etherStatsUndersizePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received that were + less than 64 octets long (excluding framing bits, + but including FCS octets) and were otherwise well + formed." + ::= { etherStatsEntry 9 } + + etherStatsOversizePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + DESCRIPTION + "The total number of packets received that were + longer than 1518 octets (excluding framing bits, + but including FCS octets) and were otherwise + well formed." + ::= { etherStatsEntry 10 } + + etherStatsFragments OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received that were not an + integral number of octets in length or that had a bad + Frame Check Sequence (FCS), and were less than 64 + octets in length (excluding framing bits but + including FCS octets)." + ::= { etherStatsEntry 11 } + + etherStatsJabbers OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received that were + longer than 1518 octets (excluding framing bits, + but including FCS octets), and were not an + integral number of octets in length or had + a bad Frame Check Sequence (FCS)." + ::= { etherStatsEntry 12 } + + etherStatsCollisions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The best estimate of the total number of collisions + on this Ethernet segment." + ::= { etherStatsEntry 13 } + + etherStatsPkts64Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including error + packets) received that were 64 octets in length + (excluding framing bits but including FCS octets)." + + + ::= { etherStatsEntry 14 } + + etherStatsPkts65to127Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including error + packets) received that were between + 65 and 127 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 15 } + + etherStatsPkts128to255Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including error + packets) received that were between + 128 and 255 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 16 } + + etherStatsPkts256to511Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including error + packets) received that were between + 256 and 511 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 17 } + + etherStatsPkts512to1023Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including error + packets) received that were between + 512 and 1023 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 18 } + + + + + + etherStatsPkts1024to1518Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including error + packets) received that were between + 1024 and 1518 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 19 } + + etherStatsOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { etherStatsEntry 20 } + + etherStatsStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this etherStats entry." + ::= { etherStatsEntry 21 } + + + -- The History Group + + -- Implementation of the History group is optional. + -- + -- The history group records periodic statistical samples from + -- a network and stores them for later retrieval. The + -- historyControl table stores configuration entries that each + -- define an interface, polling period, and other parameters. + -- Once samples are taken, their data is stored in an entry + -- in a media-specific table. Each such entry defines one + -- sample, and is associated with the historyControlEntry that + -- caused the sample to be taken. Currently the only media- + -- specific table defined is the etherHistoryTable, for + -- Ethernet networks. + -- + -- If the probe keeps track of the time of day, it should + -- start the first sample of the history at a time such that + -- when the next hour of the day begins, a sample is + -- started at that instant. This tends to make more + + + -- user-friendly reports, and enables comparison of reports + -- from different probes that have relatively accurate time + -- of day. + -- + -- The monitor is encouraged to add two history control entries + -- per monitored interface upon initialization that describe + -- a short term and a long term polling period. Suggested + -- parameters are 30 seconds for the short term polling + -- period and 30 minutes for the long term period. + + historyControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HistoryControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of history control entries." + ::= { history 1 } + + historyControlEntry OBJECT-TYPE + SYNTAX HistoryControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of parameters that set up a periodic + sampling of statistics." + INDEX { historyControlIndex } + ::= { historyControlTable 1 } + + HistoryControlEntry ::= SEQUENCE { + historyControlIndex INTEGER (1..65535), + historyControlDataSource OBJECT IDENTIFIER, + historyControlBucketsRequested INTEGER (1..65535), + historyControlBucketsGranted INTEGER (1..65535), + historyControlInterval INTEGER (1..3600), + historyControlOwner OwnerString, + historyControlStatus INTEGER + } + + historyControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + historyControl table. Each such entry defines a + set of samples at a particular interval for an + interface on the device." + ::= { historyControlEntry 1 } + + + historyControlDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the source of the data for + which historical data was collected and + placed in a media-specific table on behalf of this + historyControlEntry. This source can be any + interface on this device. In order to identify + a particular interface, this object shall identify + the instance of the ifIndex object, defined + in [4,6], for the desired interface. For example, + if an entry were to receive data from interface #1, + this object would be set to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the + identified interface. + + This object may not be modified if the associated + historyControlStatus object is equal to valid(1)." + ::= { historyControlEntry 2 } + + historyControlBucketsRequested OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The requested number of discrete time intervals + over which data is to be saved in the part of the + media-specific table associated with this + historyControl entry. + + When this object is created or modified, the probe + should set historyControlBucketsGranted as closely to + this object as is possible for the particular probe + implementation and available resources." + DEFVAL { 50 } + ::= { historyControlEntry 3 } + + historyControlBucketsGranted OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of discrete sampling intervals + over which data shall be saved in the part of + + + the media-specific table associated with this + historyControl entry. + + When the associated historyControlBucketsRequested + object is created or modified, the probe + should set this object as closely to the requested + value as is possible for the particular + probe implementation and available resources. The + probe must not lower this value except as a result + of a modification to the associated + historyControlBucketsRequested object. + + There will be times when the actual number of + buckets associated with this entry is less than + the value of this object. In this case, at the + end of each sampling interval, a new bucket will + be added to the media-specific table. + + When the number of buckets reaches the value of + this object and a new bucket is to be added to the + media-specific table, the oldest bucket associated + with this historyControlEntry shall be deleted by + the agent so that the new bucket can be added. + + When the value of this object changes to a value less + than the current value, entries are deleted + from the media-specific table associated with this + historyControlEntry. Enough of the oldest of these + entries shall be deleted by the agent so that their + number remains less than or equal to the new value of + this object. + + When the value of this object changes to a value + greater than the current value, the number of + associated media-specific entries may be allowed + to grow." + ::= { historyControlEntry 4 } + + historyControlInterval OBJECT-TYPE + SYNTAX INTEGER (1..3600) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The interval in seconds over which the data is + sampled for each bucket in the part of the + media-specific table associated with this + historyControl entry. This interval can + be set to any number of seconds between 1 and + + + 3600 (1 hour). + + Because the counters in a bucket may overflow at their + maximum value with no indication, a prudent manager + will take into account the possibility of overflow + in any of the associated counters. It is important + to consider the minimum time in which any counter + could overflow on a particular media type and set + the historyControlInterval object to a value less + than this interval. This is typically most + important for the 'octets' counter in any + media-specific table. For example, on an Ethernet + network, the etherHistoryOctets counter could overflow + in about one hour at the Ethernet's maximum + utilization. + + This object may not be modified if the associated + historyControlStatus object is equal to valid(1)." + DEFVAL { 1800 } + ::= { historyControlEntry 5 } + + historyControlOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { historyControlEntry 6 } + + historyControlStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this historyControl entry. + + Each instance of the media-specific table associated + with this historyControlEntry will be deleted by the + agent if this historyControlEntry is not equal to + valid(1)." + ::= { historyControlEntry 7 } + + + -- Ether History table + + etherHistoryTable OBJECT-TYPE + SYNTAX SEQUENCE OF EtherHistoryEntry + + + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of Ethernet history entries." + ::= { history 2 } + + etherHistoryEntry OBJECT-TYPE + SYNTAX EtherHistoryEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "An historical sample of Ethernet statistics on a + particular Ethernet interface. This sample is + associated with the historyControlEntry which set + up the parameters for a regular collection of these + samples." + INDEX { etherHistoryIndex , etherHistorySampleIndex } + ::= { etherHistoryTable 1 } + + EtherHistoryEntry ::= SEQUENCE { + etherHistoryIndex INTEGER (1..65535), + etherHistorySampleIndex INTEGER, + etherHistoryIntervalStart TimeTicks, + etherHistoryDropEvents Counter, + etherHistoryOctets Counter, + etherHistoryPkts Counter, + etherHistoryBroadcastPkts Counter, + etherHistoryMulticastPkts Counter, + etherHistoryCRCAlignErrors Counter, + etherHistoryUndersizePkts Counter, + etherHistoryOversizePkts Counter, + etherHistoryFragments Counter, + etherHistoryJabbers Counter, + etherHistoryCollisions Counter, + etherHistoryUtilization INTEGER (0..10000) + } + + etherHistoryIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The history of which this entry is a part. The + history identified by a particular value of this + index is the same history as identified + by the same value of historyControlIndex." + ::= { etherHistoryEntry 1 } + + + + etherHistorySampleIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies the particular + sample this entry represents among all samples + associated with the same historyControlEntry. + This index starts at 1 and increases by one + as each new sample is taken." + ::= { etherHistoryEntry 2 } + + etherHistoryIntervalStart OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the start of the interval + over which this sample was measured. If the probe + keeps track of the time of day, it should start + the first sample of the history at a time such that + when the next hour of the day begins, a sample is + started at that instant. Note that following this + rule may require the probe to delay collecting the + first sample of the history, as each sample must be + of the same interval. Also note that the sample which + is currently being collected is not accessible in this + table until the end of its interval." + ::= { etherHistoryEntry 3 } + + etherHistoryDropEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of events in which packets + were dropped by the probe due to lack of resources + during this interval. Note that this number is not + necessarily the number of packets dropped, it is just + the number of times this condition has been detected." + ::= { etherHistoryEntry 4 } + + etherHistoryOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets of data (including + + + those in bad packets) received on the + network (excluding framing bits but including + FCS octets)." + ::= { etherHistoryEntry 5 } + + etherHistoryPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets (including error packets) + received during this sampling interval." + ::= { etherHistoryEntry 6 } + + etherHistoryBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets received during this + sampling interval that were directed to the + broadcast address." + ::= { etherHistoryEntry 7 } + + etherHistoryMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets received during this + sampling interval that were directed to a + multicast address. Note that this number does not + include packets addressed to the broadcast address." + ::= { etherHistoryEntry 8 } + + etherHistoryCRCAlignErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received during this + sampling interval that had a length (excluding + framing bits but including FCS octets) between + 64 and 1518 octets, inclusive, but were not an + integral number of octets in length or had a + bad Frame Check Sequence (FCS)." + ::= { etherHistoryEntry 9 } + + + + etherHistoryUndersizePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received during this + interval that were less than 64 octets long + (excluding framing bits but including FCS + octets) and were otherwise well formed." + ::= { etherHistoryEntry 10 } + + etherHistoryOversizePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received during this + interval that were longer than 1518 octets + (excluding framing bits but including FCS + octets) but were otherwise well formed." + ::= { etherHistoryEntry 11 } + + etherHistoryFragments OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received during this + sampling interval that were not an integral + number of octets in length or that + had a bad Frame Check Sequence (FCS), and + were less than 64 octets in length (excluding + framing bits but including FCS octets)." + ::= { etherHistoryEntry 12 } + + etherHistoryJabbers OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received during this + interval that were longer than 1518 octets + (excluding framing bits but including FCS octets), + and were not an integral number of octets in + length or had a bad Frame Check Sequence (FCS)." + ::= { etherHistoryEntry 13 } + + + + + etherHistoryCollisions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The best estimate of the total number of collisions + on this Ethernet segment during this interval." + ::= { etherHistoryEntry 14 } + + etherHistoryUtilization OBJECT-TYPE + SYNTAX INTEGER (0..10000) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The best estimate of the mean physical layer + network utilization on this interface during this + interval, in hundredths of a percent." + ::= { etherHistoryEntry 15 } + + + -- The Alarm Group + + -- Implementation of the Alarm group is optional. + -- + -- The Alarm Group requires the implementation of the Event + -- group. + -- + -- The Alarm group periodically takes statistical samples from + -- variables in the probe and compares them to thresholds + -- that have been configured. The alarm table stores + -- configuration entries that each define a variable, + -- polling period, and threshold parameters. If a sample is + -- found to cross the threshold values, an event is + -- generated. Only variables that resolve to an ASN.1 + -- primitive type of INTEGER (INTEGER, Counter, + -- Gauge, or TimeTicks) may be monitored in this way. + -- + -- This function has a hysteresis mechanism to limit the + -- generation of events. This mechanism generates one event + -- as a threshold is crossed in the appropriate direction. + -- No more events are generated for that threshold until the + -- opposite threshold is crossed. + -- + -- In the case of a sampling a deltaValue, a probe may + -- implement this mechanism with more precision if it takes + -- a delta sample twice per period, each time comparing the + -- sum of the latest two samples to the threshold. This + -- allows the detection of threshold crossings + + + -- that span the sampling boundary. Note that this does not + -- require any special configuration of the threshold value. + -- It is suggested that probes implement this more precise + -- algorithm. + + alarmTable OBJECT-TYPE + SYNTAX SEQUENCE OF AlarmEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of alarm entries." + ::= { alarm 1 } + + alarmEntry OBJECT-TYPE + SYNTAX AlarmEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of parameters that set up a periodic checking + for alarm conditions." + INDEX { alarmIndex } + ::= { alarmTable 1 } + + AlarmEntry ::= SEQUENCE { + alarmIndex INTEGER (1..65535), + alarmInterval INTEGER, + alarmVariable OBJECT IDENTIFIER, + alarmSampleType INTEGER, + alarmValue INTEGER, + alarmStartupAlarm INTEGER, + alarmRisingThreshold INTEGER, + alarmFallingThreshold INTEGER, + alarmRisingEventIndex INTEGER (1..65535), + alarmFallingEventIndex INTEGER (1..65535), + alarmOwner OwnerString, + alarmStatus INTEGER + } + + alarmIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + alarm table. Each such entry defines a + diagnostic sample at a particular interval + for an object on the device." + ::= { alarmEntry 1 } + + + alarmInterval OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The interval in seconds over which the data is + sampled and compared with the rising and falling + thresholds. When setting this variable, care + should be given to ensure that the variable being + monitored will not exceed 2^31 - 1 and roll + over the alarmValue object during the interval. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 2 } + + alarmVariable OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The object identifier of the particular variable to + be sampled. Only variables that resolve to an ASN.1 + primitive type of INTEGER (INTEGER, Counter, Gauge, + or TimeTicks) may be sampled. + + Because SNMP access control is articulated entirely + in terms of the contents of MIB views, no access + control mechanism exists that can restrict the value of + this object to identify only those objects that exist + in a particular MIB view. Because there is thus no + acceptable means of restricting the read access that + could be obtained through the alarm mechanism, the + probe must only grant write access to this object in + those views that have read access to all objects on + the probe. + + During a set operation, if the supplied variable + name is not available in the selected MIB view, a + badValue error must be returned. If at any time + the variable name of an established alarmEntry is + no longer available in the selected MIB view, the + probe must change the status of this alarmEntry + to invalid(4). + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 3 } + + + alarmSampleType OBJECT-TYPE + SYNTAX INTEGER { + absoluteValue(1), + deltaValue(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The method of sampling the selected variable and + calculating the value to be compared against the + thresholds. If the value of this object is + absoluteValue(1), the value of the selected variable + will be compared directly with the thresholds at the + end of the sampling interval. If the value of this + object is deltaValue(2), the value of the selected + variable at the last sample will be subtracted from + the current value, and the difference compared with + the thresholds. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 4 } + + alarmValue OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of the statistic during the last sampling + period. The value during the current sampling period + is not made available until the period is completed." + ::= { alarmEntry 5 } + + alarmStartupAlarm OBJECT-TYPE + SYNTAX INTEGER { + risingAlarm(1), + fallingAlarm(2), + risingOrFallingAlarm(3) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The alarm that may be sent when this entry is first + set to valid. If the first sample after this entry + becomes valid is greater than or equal to the + risingThreshold and alarmStartupAlarm is equal to + risingAlarm(1) or risingOrFallingAlarm(3), then a + single rising alarm will be generated. If the first + + + sample after this entry becomes valid is less than + or equal to the fallingThreshold and + alarmStartupAlarm is equal to fallingAlarm(2) or + risingOrFallingAlarm(3), then a single falling + alarm will be generated. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 6 } + + alarmRisingThreshold OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A threshold for the sampled statistic. When the + current sampled value is greater than or equal to + this threshold, and the value at the last sampling + interval was less than this threshold, a single + event will be generated. + A single event will also be generated if the first + sample after this entry becomes valid is greater + than or equal to this threshold and the associated + alarmStartupAlarm is equal to risingAlarm(1) or + risingOrFallingAlarm(3). + + After a rising event is generated, another such event + will not be generated until the sampled value + falls below this threshold and reaches the + alarmFallingThreshold. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 7 } + + alarmFallingThreshold OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A threshold for the sampled statistic. When the + current sampled value is less than or equal to + this threshold, and the value at the last sampling + interval was greater than this threshold, a single + event will be generated. + A single event will also be generated if the first + sample after this entry becomes valid is less than or + equal to this threshold and the associated + + + alarmStartupAlarm is equal to fallingAlarm(2) or + risingOrFallingAlarm(3). + + After a falling event is generated, another such event + will not be generated until the sampled value + rises above this threshold and reaches the + alarmRisingThreshold. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 8 } + + alarmRisingEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The index of the eventEntry that is + used when a rising threshold is crossed. The + eventEntry identified by a particular value of + this index is the same as identified by the same value + of the eventIndex object. If there is no + corresponding entry in the eventTable, then + no association exists. In particular, if this value + is zero, no associated event will be generated, as + zero is not a valid event index. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 9 } + + alarmFallingEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The index of the eventEntry that is + used when a falling threshold is crossed. The + eventEntry identified by a particular value of + this index is the same as identified by the same value + of the eventIndex object. If there is no + corresponding entry in the eventTable, then + no association exists. In particular, if this value + is zero, no associated event will be generated, as + zero is not a valid event index. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + + + ::= { alarmEntry 10 } + + alarmOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { alarmEntry 11 } + + alarmStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this alarm entry." + ::= { alarmEntry 12 } + + + -- The Host Group + + -- Implementation of the Host group is optional. + -- + -- The host group discovers new hosts on the network by + -- keeping a list of source and destination MAC Addresses seen + -- in good packets. For each of these addresses, the host + -- group keeps a set of statistics. The hostControlTable + -- controls which interfaces this function is performed on, + -- and contains some information about the process. On + -- behalf of each hostControlEntry, data is collected on an + -- interface and placed both the hostTable and the + -- hostTimeTable. If the monitoring device finds itself + -- short of resources, it may delete entries as needed. It + -- is suggested that the device delete the least recently + -- used entries first. + + -- The hostTable contains entries for each address + -- discovered on a particular interface. Each entry + -- contains statistical data about that host. This table + -- is indexed by the MAC address of the host, through + -- which a random access may be achieved. + + -- The hostTimeTable contains data in the same format as the + -- hostTable, and must contain the same set of hosts, but is + -- indexed using hostTimeCreationOrder rather than hostAddress. + -- The hostTimeCreationOrder is an integer which reflects + -- the relative order in which a particular entry was + + + -- discovered and thus inserted into the table. As this + -- order, and thus index, is among those entries currently + -- in the table, the index for a particular entry may change + -- if an (earlier) entry is deleted. Thus the association + -- between hostTimeCreationOrder and hostTimeEntry may be + -- broken at any time. + + -- The hostTimeTable has two important uses. The first is the + -- fast download of this potentially large table. Because the + -- index of this table runs from 1 to the size of the table, + -- inclusive, its values are predictable. This allows very + -- efficient packing of variables into SNMP PDU's and allows + -- a table transfer to have multiple packets outstanding. + -- These benefits increase transfer rates tremendously. + + -- The second use of the hostTimeTable is the efficient + -- discovery by the management station of new entries added + -- to the table. After the management station has + -- downloaded the entire table, it knows that new entries + -- will be added immediately after the end of the current + -- table. It can thus detect new entries there + -- and retrieve them easily. + + -- Because the association between hostTimeCreationOrder and + -- hostTimeEntry may be broken at any time, the management + -- station must monitor the related hostControlLastDeleteTime + -- object. When the management station thus detects a deletion, + -- it must assume that any such associations have been broken, + -- and invalidate any it has stored locally. This includes + -- restarting any download of the hostTimeTable that may have + -- been in progress, as well as rediscovering the end of the + -- hostTimeTable so that it may detect new entries. If the + -- management station does not detect the broken association, + -- it may continue to refer to a particular host by its + -- creationOrder while unwittingly retrieving the data + -- associated with another host entirely. If this happens + -- while downloading the host table, the management station + -- may fail to download all of the entries in the table. + + + hostControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of host table control entries." + ::= { hosts 1 } + + + + hostControlEntry OBJECT-TYPE + SYNTAX HostControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of parameters that set up the discovery of + hosts on a particular interface and the collection + of statistics about these hosts." + INDEX { hostControlIndex } + ::= { hostControlTable 1 } + + HostControlEntry ::= SEQUENCE { + hostControlIndex INTEGER (1..65535), + hostControlDataSource OBJECT IDENTIFIER, + hostControlTableSize INTEGER, + hostControlLastDeleteTime TimeTicks, + hostControlOwner OwnerString, + hostControlStatus INTEGER + } + + hostControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + hostControl table. Each such entry defines + a function that discovers hosts on a particular + interface and places statistics about them in the + hostTable and the hostTimeTable on behalf of this + hostControlEntry." + ::= { hostControlEntry 1 } + + hostControlDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the source of the data for + this instance of the host function. This source + can be any interface on this device. In order + to identify a particular interface, this object shall + identify the instance of the ifIndex object, defined + in [4,6], for the desired interface. For example, + if an entry were to receive data from interface #1, + this object would be set to ifIndex.1. + + The statistics in this group reflect all packets + + + on the local network segment attached to the + identified interface. + + This object may not be modified if the associated + hostControlStatus object is equal to valid(1)." + ::= { hostControlEntry 2 } + + hostControlTableSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of hostEntries in the hostTable and the + hostTimeTable associated with this hostControlEntry." + ::= { hostControlEntry 3 } + + hostControlLastDeleteTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when the last entry + was deleted from the portion of the hostTable + associated with this hostControlEntry. If no + deletions have occurred, this value shall be zero." + ::= { hostControlEntry 4 } + + hostControlOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { hostControlEntry 5 } + + hostControlStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this hostControl entry. + + If this object is not equal to valid(1), all + associated entries in the hostTable, + hostTimeTable, and the hostTopNTable shall be + deleted by the agent." + ::= { hostControlEntry 6 } + + + hostTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of host entries." + ::= { hosts 2 } + + hostEntry OBJECT-TYPE + SYNTAX HostEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for a particular host + that has been discovered on an interface of this + device." + INDEX { hostIndex, hostAddress } + ::= { hostTable 1 } + + HostEntry ::= SEQUENCE { + hostAddress OCTET STRING, + hostCreationOrder INTEGER (1..65535), + hostIndex INTEGER (1..65535), + hostInPkts Counter, + hostOutPkts Counter, + hostInOctets Counter, + hostOutOctets Counter, + hostOutErrors Counter, + hostOutBroadcastPkts Counter, + hostOutMulticastPkts Counter + } + + hostAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The physical address of this host." + ::= { hostEntry 1 } + + hostCreationOrder OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that defines the relative ordering of + the creation time of hosts captured for a + particular hostControlEntry. This index shall + + + be between 1 and N, where N is the value of + the associated hostControlTableSize. The ordering + of the indexes is based on the order of each entry's + insertion into the table, in which entries added + earlier have a lower index value than entries added + later. + + It is important to note that the order for a + particular entry may change as an (earlier) entry + is deleted from the table. Because this order may + change, management stations should make use of the + hostControlLastDeleteTime variable in the + hostControlEntry associated with the relevant + portion of the hostTable. By observing + this variable, the management station may detect + the circumstances where a previous association + between a value of hostCreationOrder + and a hostEntry may no longer hold." + ::= { hostEntry 2 } + + hostIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The set of collected host statistics of which + this entry is a part. The set of hosts + identified by a particular value of this + index is associated with the hostControlEntry + as identified by the same value of hostControlIndex." + ::= { hostEntry 3 } + + hostInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets without errors transmitted to + this address since it was added to the hostTable." + ::= { hostEntry 4 } + + hostOutPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets including errors transmitted + by this address since it was added to the hostTable." + + + ::= { hostEntry 5 } + + hostInOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets transmitted to this address + since it was added to the hostTable (excluding + framing bits but including FCS octets), except for + those octets in packets that contained errors." + ::= { hostEntry 6 } + + hostOutOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets transmitted by this address + since it was added to the hostTable (excluding + framing bits but including FCS octets), including + those octets in packets that contained errors." + ::= { hostEntry 7 } + + hostOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of error packets transmitted by this + address since this host was added to the hostTable." + ::= { hostEntry 8 } + + hostOutBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to the broadcast address + since this host was added to the hostTable." + ::= { hostEntry 9 } + + hostOutMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + + + "The number of good packets transmitted by this + address that were directed to a multicast address + since this host was added to the hostTable. + Note that this number does not include packets + directed to the broadcast address." + ::= { hostEntry 10 } + + + -- host Time Table + + hostTimeTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostTimeEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of time-ordered host table entries." + ::= { hosts 3 } + + hostTimeEntry OBJECT-TYPE + SYNTAX HostTimeEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for a particular host + that has been discovered on an interface of this + device. This collection includes the relative + ordering of the creation time of this object." + INDEX { hostTimeIndex, hostTimeCreationOrder } + ::= { hostTimeTable 1 } + + HostTimeEntry ::= SEQUENCE { + hostTimeAddress OCTET STRING, + hostTimeCreationOrder INTEGER (1..65535), + hostTimeIndex INTEGER (1..65535), + hostTimeInPkts Counter, + hostTimeOutPkts Counter, + hostTimeInOctets Counter, + hostTimeOutOctets Counter, + hostTimeOutErrors Counter, + hostTimeOutBroadcastPkts Counter, + hostTimeOutMulticastPkts Counter + } + + hostTimeAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + + + "The physical address of this host." + ::= { hostTimeEntry 1 } + + hostTimeCreationOrder OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in + the hostTime table among those entries associated + with the same hostControlEntry. This index shall + be between 1 and N, where N is the value of + the associated hostControlTableSize. The ordering + of the indexes is based on the order of each entry's + insertion into the table, in which entries added + earlier have a lower index value than entries added + later. Thus the management station has the ability + to learn of new entries added to this table without + downloading the entire table. + + It is important to note that the index for a + particular entry may change as an (earlier) entry + is deleted from the table. Because this order may + change, management stations should make use of the + hostControlLastDeleteTime variable in the + hostControlEntry associated with the relevant + portion of the hostTimeTable. By observing + this variable, the management station may detect + the circumstances where a download of the table + may have missed entries, and where a previous + association between a value of hostTimeCreationOrder + and a hostTimeEntry may no longer hold." + ::= { hostTimeEntry 2 } + + hostTimeIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The set of collected host statistics of which + this entry is a part. The set of hosts + identified by a particular value of this + index is associated with the hostControlEntry + as identified by the same value of hostControlIndex." + ::= { hostTimeEntry 3 } + + + + + + hostTimeInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets without errors transmitted to + this address since it was added to the hostTimeTable." + ::= { hostTimeEntry 4 } + + hostTimeOutPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets including errors transmitted + by this address since it was added to the + hostTimeTable." + ::= { hostTimeEntry 5 } + + hostTimeInOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets transmitted to this address + since it was added to the hostTimeTable (excluding + framing bits but including FCS octets), except for + those octets in packets that contained errors." + ::= { hostTimeEntry 6 } + + hostTimeOutOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets transmitted by this address since + it was added to the hostTimeTable (excluding framing + bits but including FCS octets), including those + octets in packets that contained errors." + ::= { hostTimeEntry 7 } + + hostTimeOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of error packets transmitted by this + address since this host was added to the + + + hostTimeTable." + ::= { hostTimeEntry 8 } + + hostTimeOutBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to the broadcast address + since this host was added to the hostTimeTable." + ::= { hostTimeEntry 9 } + + hostTimeOutMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to a multicast address + since this host was added to the hostTimeTable. + Note that this number does not include packets + directed to the broadcast address." + ::= { hostTimeEntry 10 } + + + -- The Host Top "N" Group + + -- Implementation of the Host Top N group is optional. + -- + -- The Host Top N group requires the implementation of the + -- host group. + -- + -- The Host Top N group is used to prepare reports that + -- describe the hosts that top a list ordered by one of + -- their statistics. The available statistics are samples + -- of one of their base statistics, over an interval + -- specified by the management station. Thus, these + -- statistics are rate based. The management + -- station also selects how many such hosts are reported. + + -- The hostTopNControlTable is used to initiate the generation + -- of such a report. The management station may select the + -- parameters of such a report, such as which interface, + -- which statistic, how many hosts, and the start and stop + -- times of the sampling. When the report is prepared, + -- entries are created in the hostTopNTable associated with + -- the relevant hostTopNControlEntry. These entries are + + + -- static for each report after it has been prepared. + + hostTopNControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostTopNControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of top N host control entries." + ::= { hostTopN 1 } + + hostTopNControlEntry OBJECT-TYPE + SYNTAX HostTopNControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of parameters that control the creation of a + report of the top N hosts according to several + metrics." + INDEX { hostTopNControlIndex } + ::= { hostTopNControlTable 1 } + + HostTopNControlEntry ::= SEQUENCE { + hostTopNControlIndex INTEGER (1..65535), + hostTopNHostIndex INTEGER (1..65535), + hostTopNRateBase INTEGER, + hostTopNTimeRemaining INTEGER, + hostTopNDuration INTEGER, + hostTopNRequestedSize INTEGER, + hostTopNGrantedSize INTEGER, + hostTopNStartTime TimeTicks, + hostTopNOwner OwnerString, + hostTopNStatus INTEGER + } + + hostTopNControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the hostTopNControl table. Each such + entry defines one top N report prepared for + one interface." + ::= { hostTopNControlEntry 1 } + + hostTopNHostIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + + + STATUS mandatory + DESCRIPTION + "The host table for which a top N report will be + prepared on behalf of this entry. The host table + identified by a particular value of this index is + associated with the same host table as identified + by the same value of hostIndex. + + This object may not be modified if the associated + hostTopNStatus object is equal to valid(1)." + ::= { hostTopNControlEntry 2 } + + hostTopNRateBase OBJECT-TYPE + SYNTAX INTEGER { + hostTopNInPkts(1), + hostTopNOutPkts(2), + hostTopNInOctets(3), + hostTopNOutOctets(4), + hostTopNOutErrors(5), + hostTopNOutBroadcastPkts(6), + hostTopNOutMulticastPkts(7) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The variable for each host that the hostTopNRate + variable is based upon. + + This object may not be modified if the associated + hostTopNStatus object is equal to valid(1)." + ::= { hostTopNControlEntry 3 } + + hostTopNTimeRemaining OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The number of seconds left in the report currently + being collected. When this object is modified by + the management station, a new collection is started, + possibly aborting a currently running report. The + new value is used as the requested duration of this + report, which is loaded into the associated + hostTopNDuration object. + + When this object is set to a non-zero value, any + associated hostTopNEntries shall be made + inaccessible by the monitor. While the value of this + + + object is non-zero, it decrements by one per second + until it reaches zero. During this time, all + associated hostTopNEntries shall remain + inaccessible. At the time that this object + decrements to zero, the report is made + accessible in the hostTopNTable. Thus, the hostTopN + table needs to be created only at the end of the + collection interval." + DEFVAL { 0 } + ::= { hostTopNControlEntry 4 } + + hostTopNDuration OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of seconds that this report has collected + during the last sampling interval, or if this + report is currently being collected, the number + of seconds that this report is being collected + during this sampling interval. + + When the associated hostTopNTimeRemaining object is + set, this object shall be set by the probe to the + same value and shall not be modified until the next + time the hostTopNTimeRemaining is set. + + This value shall be zero if no reports have been + requested for this hostTopNControlEntry." + DEFVAL { 0 } + ::= { hostTopNControlEntry 5 } + + hostTopNRequestedSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The maximum number of hosts requested for the top N + table. + + When this object is created or modified, the probe + should set hostTopNGrantedSize as closely to this + object as is possible for the particular probe + implementation and available resources." + DEFVAL { 10 } + ::= { hostTopNControlEntry 6 } + + + + + hostTopNGrantedSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum number of hosts in the top N table. + + When the associated hostTopNRequestedSize object is + created or modified, the probe should set this + object as closely to the requested value as is + possible for the particular implementation and + available resources. The probe must not lower this + value except as a result of a set to the associated + hostTopNRequestedSize object. + + Hosts with the highest value of hostTopNRate shall be + placed in this table in decreasing order of this rate + until there is no more room or until there are no more + hosts." + ::= { hostTopNControlEntry 7 } + + hostTopNStartTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when this top N report was + last started. In other words, this is the time that + the associated hostTopNTimeRemaining object was + modified to start the requested report." + ::= { hostTopNControlEntry 8 } + + hostTopNOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { hostTopNControlEntry 9 } + + hostTopNStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this hostTopNControl entry. + + + + If this object is not equal to valid(1), all + associated hostTopNEntries shall be deleted by + the agent." + ::= { hostTopNControlEntry 10 } + + hostTopNTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostTopNEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of top N host entries." + ::= { hostTopN 2 } + + hostTopNEntry OBJECT-TYPE + SYNTAX HostTopNEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of statistics for a host that is part of a + top N report." + INDEX { hostTopNReport, hostTopNIndex } + ::= { hostTopNTable 1 } + + HostTopNEntry ::= SEQUENCE { + hostTopNReport INTEGER (1..65535), + hostTopNIndex INTEGER (1..65535), + hostTopNAddress OCTET STRING, + hostTopNRate INTEGER + } + + hostTopNReport OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "This object identifies the top N report of which + this entry is a part. The set of hosts + identified by a particular value of this + object is part of the same report as identified + by the same value of the hostTopNControlIndex object." + ::= { hostTopNEntry 1 } + + hostTopNIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in + + + the hostTopN table among those in the same report. + This index is between 1 and N, where N is the + number of entries in this table. Increasing values + of hostTopNIndex shall be assigned to entries with + decreasing values of hostTopNRate until index N + is assigned to the entry with the lowest value of + hostTopNRate or there are no more hostTopNEntries." + ::= { hostTopNEntry 2 } + + hostTopNAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The physical address of this host." + ::= { hostTopNEntry 3 } + + hostTopNRate OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The amount of change in the selected variable + during this sampling interval. The selected + variable is this host's instance of the object + selected by hostTopNRateBase." + ::= { hostTopNEntry 4 } + + + -- The Matrix Group + + -- Implementation of the Matrix group is optional. + -- + -- The Matrix group consists of the matrixControlTable, + -- matrixSDTable and the matrixDSTable. These tables + -- store statistics for a particular conversation between + -- two addresses. As the device detects a new conversation, + -- including those to a non-unicast address, it creates a + -- new entry in both of the matrix tables. + -- It must only create new entries based on information + -- received in good packets. If the monitoring device finds + -- itself short of resources, it may delete entries as needed. + -- It is suggested that the device delete the least recently + -- used entries first. + + matrixControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixControlEntry + ACCESS not-accessible + + + STATUS mandatory + DESCRIPTION + "A list of information entries for the + traffic matrix on each interface." + ::= { matrix 1 } + + matrixControlEntry OBJECT-TYPE + SYNTAX MatrixControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about a traffic matrix on a + particular interface." + INDEX { matrixControlIndex } + ::= { matrixControlTable 1 } + + MatrixControlEntry ::= SEQUENCE { + matrixControlIndex INTEGER (1..65535), + matrixControlDataSource OBJECT IDENTIFIER, + matrixControlTableSize INTEGER, + matrixControlLastDeleteTime TimeTicks, + matrixControlOwner OwnerString, + matrixControlStatus INTEGER + } + + matrixControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + matrixControl table. Each such entry defines + a function that discovers conversations on a particular + interface and places statistics about them in the + matrixSDTable and the matrixDSTable on behalf of this + matrixControlEntry." + ::= { matrixControlEntry 1 } + + matrixControlDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the source of + the data from which this entry creates a traffic matrix. + This source can be any interface on this device. In + order to identify a particular interface, this object + shall identify the instance of the ifIndex object, + + + defined in [4,6], for the desired interface. For + example, if an entry were to receive data from + interface #1, this object would be set to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the + identified interface. + + This object may not be modified if the associated + matrixControlStatus object is equal to valid(1)." + ::= { matrixControlEntry 2 } + + matrixControlTableSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of matrixSDEntries in the matrixSDTable + for this interface. This must also be the value of + the number of entries in the matrixDSTable for this + interface." + ::= { matrixControlEntry 3 } + + matrixControlLastDeleteTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when the last entry + was deleted from the portion of the matrixSDTable + or matrixDSTable associated with this + matrixControlEntry. + If no deletions have occurred, this value shall be + zero." + ::= { matrixControlEntry 4 } + + matrixControlOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { matrixControlEntry 5 } + + matrixControlStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + + + STATUS mandatory + DESCRIPTION + "The status of this matrixControl entry. + + If this object is not equal to valid(1), all + associated entries in the matrixSDTable and the + matrixDSTable shall be deleted by the agent." + ::= { matrixControlEntry 6 } + + matrixSDTable OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixSDEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of traffic matrix entries indexed by + source and destination MAC address." + ::= { matrix 2 } + + matrixSDEntry OBJECT-TYPE + SYNTAX MatrixSDEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for communications between + two addresses on a particular interface." + INDEX { matrixSDIndex, + matrixSDSourceAddress, matrixSDDestAddress } + ::= { matrixSDTable 1 } + + MatrixSDEntry ::= SEQUENCE { + matrixSDSourceAddress OCTET STRING, + matrixSDDestAddress OCTET STRING, + matrixSDIndex INTEGER (1..65535), + matrixSDPkts Counter, + matrixSDOctets Counter, + matrixSDErrors Counter + } + + matrixSDSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The source physical address." + ::= { matrixSDEntry 1 } + + + + + + matrixSDDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The destination physical address." + ::= { matrixSDEntry 2 } + + matrixSDIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The set of collected matrix statistics of which + this entry is a part. The set of matrix statistics + identified by a particular value of this index + is associated with the same matrixControlEntry + as identified by the same value of matrixControlIndex." + ::= { matrixSDEntry 3 } + + matrixSDPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets transmitted from the source + address to the destination address (this number + includes error packets)." + ::= { matrixSDEntry 4 } + + matrixSDOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets (excluding framing bits but + including FCS octets) contained in all packets + transmitted from the source address to the + destination address." + ::= { matrixSDEntry 5 } + + matrixSDErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of error packets transmitted from + the source address to the destination address." + + + ::= { matrixSDEntry 6 } + + + -- Traffic matrix tables from destination to source + + matrixDSTable OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixDSEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of traffic matrix entries indexed by + destination and source MAC address." + ::= { matrix 3 } + + matrixDSEntry OBJECT-TYPE + SYNTAX MatrixDSEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for communications between + two address on a particular interface." + INDEX { matrixDSIndex, + matrixDSDestAddress, matrixDSSourceAddress } + ::= { matrixDSTable 1 } + + MatrixDSEntry ::= SEQUENCE { + matrixDSSourceAddress OCTET STRING, + matrixDSDestAddress OCTET STRING, + matrixDSIndex INTEGER (1..65535), + matrixDSPkts Counter, + matrixDSOctets Counter, + matrixDSErrors Counter + } + + matrixDSSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The source physical address." + ::= { matrixDSEntry 1 } + + matrixDSDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The destination physical address." + + + ::= { matrixDSEntry 2 } + + matrixDSIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The set of collected matrix statistics of which + this entry is a part. The set of matrix statistics + identified by a particular value of this index + is associated with the same matrixControlEntry + as identified by the same value of matrixControlIndex." + ::= { matrixDSEntry 3 } + + matrixDSPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets transmitted from the source + address to the destination address (this number + includes error packets)." + ::= { matrixDSEntry 4 } + + matrixDSOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets (excluding framing bits + but including FCS octets) contained in all packets + transmitted from the source address to the + destination address." + ::= { matrixDSEntry 5 } + + matrixDSErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of error packets transmitted from + the source address to the destination address." + ::= { matrixDSEntry 6 } + + + -- The Filter Group + + -- Implementation of the Filter group is optional. + + + -- + -- The Filter group allows packets to be captured with an + -- arbitrary filter expression. A logical data and + -- event stream or "channel" is formed by the packets + -- that match the filter expression. + -- + -- This filter mechanism allows the creation of an arbitrary + -- logical expression with which to filter packets. Each + -- filter associated with a channel is OR'ed with the others. + -- Within a filter, any bits checked in the data and status are + -- AND'ed with respect to other bits in the same filter. The + -- NotMask also allows for checking for inequality. Finally, + -- the channelAcceptType object allows for inversion of the + -- whole equation. + -- + -- The channel can be turned on or off, and can also + -- generate events when packets pass through it. + + filterTable OBJECT-TYPE + SYNTAX SEQUENCE OF FilterEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of packet filter entries." + ::= { filter 1 } + + filterEntry OBJECT-TYPE + SYNTAX FilterEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of parameters for a packet filter applied on a + particular interface." + INDEX { filterIndex } + ::= { filterTable 1 } + + FilterEntry ::= SEQUENCE { + filterIndex INTEGER (1..65535), + filterChannelIndex INTEGER (1..65535), + filterPktDataOffset INTEGER, + filterPktData OCTET STRING, + filterPktDataMask OCTET STRING, + filterPktDataNotMask OCTET STRING, + filterPktStatus INTEGER, + filterPktStatusMask INTEGER, + filterPktStatusNotMask INTEGER, + filterOwner OwnerString, + filterStatus INTEGER + + + } + + filterIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the filter table. Each such entry defines + one filter that is to be applied to every packet + received on an interface." + ::= { filterEntry 1 } + + filterChannelIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the channel of which this + filter is a part. The filters identified by a + particular value of this object are associated + with the same channel as identified by the same + value of the channelIndex object." + ::= { filterEntry 2 } + + filterPktDataOffset OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The offset from the beginning of each packet where + a match of packet data will be attempted. This offset + is measured from the point in the physical layer + packet after the framing bits, if any. For example, + in an Ethernet frame, this point is at the beginning + of the destination MAC address. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + DEFVAL { 0 } + ::= { filterEntry 3 } + + filterPktData OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The data that is to be matched with the input packet. + + + For each packet received, this filter and the + accompanying filterPktDataMask and + filterPktDataNotMask will be adjusted for the + offset. The only bits relevant to this + match algorithm are those that have the corresponding + filterPktDataMask bit equal to one. The following + three rules are then applied to every packet: + + (1) If the packet is too short and does not have data + corresponding to part of the filterPktData, the + packet will fail this data match. + + (2) For each relevant bit from the packet with the + corresponding filterPktDataNotMask bit set to + zero, if the bit from the packet is not equal to + the corresponding bit from the filterPktData, + then the packet will fail this data match. + + (3) If for every relevant bit from the packet with the + corresponding filterPktDataNotMask bit set to one, + the bit from the packet is equal to the + corresponding bit from the filterPktData, then + the packet will fail this data match. + + Any packets that have not failed any of the three + matches above have passed this data match. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 4 } + + filterPktDataMask OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The mask that is applied to the match process. + After adjusting this mask for the offset, only those + bits in the received packet that correspond to bits + set in this mask are relevant for further processing + by the match algorithm. The offset is applied to + filterPktDataMask in the same way it is applied to + the filter. For the purposes of the matching + algorithm, if the associated filterPktData object + is longer than this mask, this mask is conceptually + extended with '1' bits until it reaches the + length of the filterPktData object. + + + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 5 } + + filterPktDataNotMask OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The inversion mask that is applied to the match + process. After adjusting this mask for the offset, + those relevant bits in the received packet that + correspond to bits cleared in this mask must all + be equal to their corresponding bits in the + filterPktData object for the packet to be accepted. + In addition, at least one of those relevant + bits in the received packet that correspond to bits + set in this mask must be different to its + corresponding bit in the filterPktData object. + + For the purposes of the matching algorithm, if + the associated filterPktData object is longer than + this mask, this mask is conceptually extended with + '0' bits until it reaches the length of the + filterPktData object. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 6 } + + filterPktStatus OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status that is to be matched with the input + packet. The only bits relevant to this match + algorithm are those that have the corresponding + filterPktStatusMask bit equal to one. + + The following two rules are then applied to every + packet: + + (1) For each relevant bit from the packet status + with the corresponding filterPktStatusNotMask + bit set to zero, if the bit from the packet + status is not equal to the corresponding bit + from the filterPktStatus, then the packet will + + + fail this status match. + + (2) If for every relevant bit from the packet status + with the corresponding filterPktStatusNotMask + bit set to one, the bit from the packet status + is equal to the corresponding bit from the + filterPktStatus, then the packet will fail + this status match. + + Any packets that have not failed either of the two + matches above have passed this status match. + + The value of the packet status is a sum. This sum + initially takes the value zero. Then, for each + error, E, that has been discovered in this packet, + 2 raised to a value representing E is added to the sum. + The errors and the bits that represent them are + dependent on the media type of the interface that + this channel is receiving packets from. + + The errors defined for a packet captured off of an + Ethernet interface are as follows: + + bit # Error + 0 Packet is longer than 1518 octets + 1 Packet is shorter than 64 octets + 2 Packet experienced a CRC or Alignment + error + + For example, an Ethernet fragment would have a + value of 6 (2^1 + 2^2). + + As this MIB is expanded to new media types, this + object will have other media-specific errors defined. + + For the purposes of this status matching algorithm, if + the packet status is longer than this + object, filterPktStatus this object is conceptually + extended with '0' bits until it reaches the size of + the packet status. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 7 } + + filterPktStatusMask OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + + + STATUS mandatory + DESCRIPTION + "The mask that is applied to the status match process. + Only those bits in the received packet that correspond + to bits set in this mask are relevant for further + processing by the status match algorithm. For the + purposes of the matching algorithm, if the + associated filterPktStatus object is longer than + this mask, this mask is conceptually extended with + '1' bits until it reaches the size of the + filterPktStatus. In addition, if a packet status is + longer than this mask, this mask is conceptually + extended with '0' bits until it reaches the size of + the packet status. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 8 } + + filterPktStatusNotMask OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The inversion mask that is applied to the status match + process. Those relevant bits in the received packet + status that correspond to bits cleared in this mask + must all be equal to their corresponding bits in the + filterPktStatus object for the packet to be accepted. + In addition, at least one of those relevant bits in the + received packet status that correspond to bits set in + this mask must be different to its corresponding bit + in the filterPktStatus object for the packet to be + accepted. + + For the purposes of the matching algorithm, if the + associated filterPktStatus object or a packet status + is longer than this mask, this mask is conceptually + extended with '0' bits until it reaches the longer of + the lengths of the filterPktStatus object and the + packet status. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 9 } + + filterOwner OBJECT-TYPE + SYNTAX OwnerString + + + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { filterEntry 10 } + + filterStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this filter entry." + ::= { filterEntry 11 } + + channelTable OBJECT-TYPE + SYNTAX SEQUENCE OF ChannelEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of packet channel entries." + ::= { filter 2 } + + channelEntry OBJECT-TYPE + SYNTAX ChannelEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of parameters for a packet channel applied on a + particular interface." + INDEX { channelIndex } + ::= { channelTable 1 } + + ChannelEntry ::= SEQUENCE { + channelIndex INTEGER (1..65535), + channelIfIndex INTEGER (1..65535), + channelAcceptType INTEGER, + channelDataControl INTEGER, + channelTurnOnEventIndex INTEGER (0..65535), + channelTurnOffEventIndex INTEGER (0..65535), + channelEventIndex INTEGER (0..65535), + channelEventStatus INTEGER, + channelMatches Counter, + channelDescription DisplayString (SIZE (0..127)), + channelOwner OwnerString, + channelStatus INTEGER + } + + + + channelIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the channel table. Each such + entry defines one channel, a logical data + and event stream." + ::= { channelEntry 1 } + + channelIfIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies the + interface on this remote network monitoring device + to which the associated filters are applied to allow + data into this channel. The interface identified by + a particular value of this object is the same + interface as identified by the same value of the + ifIndex object, defined in [4,6]. The filters in + this group are applied to all packets on the local + network segment attached to the identified + interface. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 2 } + + channelAcceptType OBJECT-TYPE + SYNTAX INTEGER { + acceptMatched(1), + acceptFailed(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object controls the action of the filters + associated with this channel. If this object is equal + to acceptMatched(1), packets will be accepted to this + channel if they are accepted by both the packet data + and packet status matches of an associated filter. If + this object is equal to acceptFailed(2), packets will + be accepted to this channel only if they fail either + the packet data match or the packet status match of + each of the associated filters. + + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 3 } + + channelDataControl OBJECT-TYPE + SYNTAX INTEGER { + on(1), + off(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object controls the flow of data through this + channel. If this object is on(1), data, status and + events flow through this channel. If this object is + off(2), data, status and events will not flow through + this channel." + DEFVAL { off } + ::= { channelEntry 4 } + + channelTurnOnEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The value of this object identifies the event + that is configured to turn the associated + channelDataControl from off to on when the event is + generated. The event identified by a particular value + of this object is the same event as identified by the + same value of the eventIndex object. If there is no + corresponding entry in the eventTable, then no + association exists. In fact, if no event is intended + for this channel, channelTurnOnEventIndex must be + set to zero, a non-existent event index. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 5 } + + channelTurnOffEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The value of this object identifies the event + that is configured to turn the associated + channelDataControl from on to off when the event is + + + generated. The event identified by a particular value + of this object is the same event as identified by the + same value of the eventIndex object. If there is no + corresponding entry in the eventTable, then no + association exists. In fact, if no event is intended + for this channel, channelTurnOffEventIndex must be + set to zero, a non-existent event index. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 6 } + + channelEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The value of this object identifies the event + that is configured to be generated when the + associated channelDataControl is on and a packet + is matched. The event identified by a particular value + of this object is the same event as identified by the + same value of the eventIndex object. If there is no + corresponding entry in the eventTable, then no + association exists. In fact, if no event is intended + for this channel, channelEventIndex must be + set to zero, a non-existent event index. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 7 } + + channelEventStatus OBJECT-TYPE + SYNTAX INTEGER { + eventReady(1), + eventFired(2), + eventAlwaysReady(3) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The event status of this channel. + + If this channel is configured to generate events + when packets are matched, a means of controlling + the flow of those events is often needed. When + this object is equal to eventReady(1), a single + event may be generated, after which this object + + + will be set by the probe to eventFired(2). While + in the eventFired(2) state, no events will be + generated until the object is modified to + eventReady(1) (or eventAlwaysReady(3)). The + management station can thus easily respond to a + notification of an event by re-enabling this object. + + If the management station wishes to disable this + flow control and allow events to be generated + at will, this object may be set to + eventAlwaysReady(3). Disabling the flow control + is discouraged as it can result in high network + traffic or other performance problems." + DEFVAL { eventReady } + ::= { channelEntry 8 } + + channelMatches OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times this channel has matched a packet. + Note that this object is updated even when + channelDataControl is set to off." + ::= { channelEntry 9 } + + channelDescription OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..127)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A comment describing this channel." + ::= { channelEntry 10 } + + channelOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { channelEntry 11 } + + channelStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + + + "The status of this channel entry." + ::= { channelEntry 12 } + + + -- The Packet Capture Group + + -- Implementation of the Packet Capture group is optional. + -- + -- The Packet Capture Group requires implementation of the + -- Filter Group. + -- + -- The Packet Capture group allows packets to be captured + -- upon a filter match. The bufferControlTable controls + -- the captured packets output from a channel that is + -- associated with it. The captured packets are placed + -- in entries in the captureBufferTable. These entries are + -- associated with the bufferControlEntry on whose behalf they + -- were stored. + + bufferControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF BufferControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of buffers control entries." + ::= { capture 1 } + + bufferControlEntry OBJECT-TYPE + SYNTAX BufferControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of parameters that control the collection of + a stream of packets that have matched filters." + INDEX { bufferControlIndex } + ::= { bufferControlTable 1 } + + BufferControlEntry ::= SEQUENCE { + bufferControlIndex INTEGER (1..65535), + bufferControlChannelIndex INTEGER (1..65535), + bufferControlFullStatus INTEGER, + bufferControlFullAction INTEGER, + bufferControlCaptureSliceSize INTEGER, + bufferControlDownloadSliceSize INTEGER, + bufferControlDownloadOffset INTEGER, + bufferControlMaxOctetsRequested INTEGER, + bufferControlMaxOctetsGranted INTEGER, + bufferControlCapturedPackets INTEGER, + + + bufferControlTurnOnTime TimeTicks, + bufferControlOwner OwnerString, + bufferControlStatus INTEGER + } + + bufferControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the bufferControl table. The value of this + index shall never be zero. Each such + entry defines one set of packets that is + captured and controlled by one or more filters." + ::= { bufferControlEntry 1 } + + bufferControlChannelIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An index that identifies the channel that is the + source of packets for this bufferControl table. + The channel identified by a particular value of this + index is the same as identified by the same value of + the channelIndex object. + + This object may not be modified if the associated + bufferControlStatus object is equal to valid(1)." + ::= { bufferControlEntry 2 } + + bufferControlFullStatus OBJECT-TYPE + SYNTAX INTEGER { + spaceAvailable(1), + full(2) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "This object shows whether the buffer has room to + accept new packets or if it is full. + + If the status is spaceAvailable(1), the buffer is + accepting new packets normally. If the status is + full(2) and the associated bufferControlFullAction + object is wrapWhenFull, the buffer is accepting new + packets by deleting enough of the oldest packets + + + to make room for new ones as they arrive. Otherwise, + if the status is full(2) and the + bufferControlFullAction object is lockWhenFull, + then the buffer has stopped collecting packets. + + When this object is set to full(2) the probe must + not later set it to spaceAvailable(1) except in the + case of a significant gain in resources such as + an increase of bufferControlOctetsGranted. In + particular, the wrap-mode action of deleting old + packets to make room for newly arrived packets + must not affect the value of this object." + ::= { bufferControlEntry 3 } + + bufferControlFullAction OBJECT-TYPE + SYNTAX INTEGER { + lockWhenFull(1), + wrapWhenFull(2) -- FIFO + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Controls the action of the buffer when it + reaches the full status. When in the lockWhenFull(1) + state a packet is added to the buffer that + fills the buffer, the bufferControlFullStatus will + be set to full(2) and this buffer will stop capturing + packets." + ::= { bufferControlEntry 4 } + + bufferControlCaptureSliceSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The maximum number of octets of each packet + that will be saved in this capture buffer. + For example, if a 1500 octet packet is received by + the probe and this object is set to 500, then only + 500 octets of the packet will be stored in the + associated capture buffer. If this variable is set + to 0, the capture buffer will save as many octets + as is possible. + + This object may not be modified if the associated + bufferControlStatus object is equal to valid(1)." + DEFVAL { 100 } + ::= { bufferControlEntry 5 } + + + bufferControlDownloadSliceSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The maximum number of octets of each packet + in this capture buffer that will be returned in + an SNMP retrieval of that packet. For example, + if 500 octets of a packet have been stored in the + associated capture buffer, the associated + bufferControlDownloadOffset is 0, and this + object is set to 100, then the captureBufferPacket + object that contains the packet will contain only + the first 100 octets of the packet. + + A prudent manager will take into account possible + interoperability or fragmentation problems that may + occur if the download slice size is set too large. + In particular, conformant SNMP implementations are not + required to accept messages whose length exceeds 484 + octets, although they are encouraged to support larger + datagrams whenever feasible." + DEFVAL { 100 } + ::= { bufferControlEntry 6 } + + bufferControlDownloadOffset OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The offset of the first octet of each packet + in this capture buffer that will be returned in + an SNMP retrieval of that packet. For example, + if 500 octets of a packet have been stored in the + associated capture buffer and this object is set to + 100, then the captureBufferPacket object that + contains the packet will contain bytes starting + 100 octets into the packet." + DEFVAL { 0 } + ::= { bufferControlEntry 7 } + + bufferControlMaxOctetsRequested OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The requested maximum number of octets to be + saved in this captureBuffer, including any + + + implementation-specific overhead. If this variable + is set to -1, the capture buffer will save as many + octets as is possible. + + When this object is created or modified, the probe + should set bufferControlMaxOctetsGranted as closely + to this object as is possible for the particular probe + implementation and available resources. However, if + the object has the special value of -1, the probe + must set bufferControlMaxOctetsGranted to -1." + DEFVAL { -1 } + ::= { bufferControlEntry 8 } + + bufferControlMaxOctetsGranted OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum number of octets that can be + saved in this captureBuffer, including overhead. + If this variable is -1, the capture buffer will save + as many octets as possible. + + When the bufferControlMaxOctetsRequested object is + created or modified, the probe should set this object + as closely to the requested value as is possible for + the particular probe implementation and available + resources. However, if the request object has the + special value of -1, the probe must set this object + to -1. The probe must not lower this value except + as a result of a modification to the associated + bufferControlMaxOctetsRequested object. + + When this maximum number of octets is reached + and a new packet is to be added to this + capture buffer and the corresponding + bufferControlFullAction is set to wrapWhenFull(2), + enough of the oldest packets associated with this + capture buffer shall be deleted by the agent so + that the new packet can be added. If the + corresponding bufferControlFullAction is set to + lockWhenFull(1), the new packet shall be discarded. + In either case, the probe must set + bufferControlFullStatus to full(2). + + When the value of this object changes to a value less + than the current value, entries are deleted from + the captureBufferTable associated with this + + + bufferControlEntry. Enough of the + oldest of these captureBufferEntries shall be + deleted by the agent so that the number of octets + used remains less than or equal to the new value of + this object. + + When the value of this object changes to a value greater + than the current value, the number of associated + captureBufferEntries may be allowed to grow." + ::= { bufferControlEntry 9 } + + bufferControlCapturedPackets OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets currently in this captureBuffer." + ::= { bufferControlEntry 10 } + + bufferControlTurnOnTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when this capture buffer was + first turned on." + ::= { bufferControlEntry 11 } + + bufferControlOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { bufferControlEntry 12 } + + bufferControlStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this buffer Control Entry." + ::= { bufferControlEntry 13 } + + captureBufferTable OBJECT-TYPE + SYNTAX SEQUENCE OF CaptureBufferEntry + ACCESS not-accessible + + + STATUS mandatory + DESCRIPTION + "A list of packets captured off of a channel." + ::= { capture 2 } + + captureBufferEntry OBJECT-TYPE + SYNTAX CaptureBufferEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A packet captured off of an attached network." + INDEX { captureBufferControlIndex, captureBufferIndex } + ::= { captureBufferTable 1 } + + CaptureBufferEntry ::= SEQUENCE { + captureBufferControlIndex INTEGER (1..65535), + captureBufferIndex INTEGER, + captureBufferPacketID INTEGER, + captureBufferPacketData OCTET STRING, + captureBufferPacketLength INTEGER, + captureBufferPacketTime INTEGER, + captureBufferPacketStatus INTEGER + } + + captureBufferControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The index of the bufferControlEntry with which + this packet is associated." + ::= { captureBufferEntry 1 } + + captureBufferIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the captureBuffer table associated with a + particular bufferControlEntry. This index will + start at 1 and increase by one for each new packet + added with the same captureBufferControlIndex." + ::= { captureBufferEntry 2 } + + captureBufferPacketID OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + + + STATUS mandatory + DESCRIPTION + "An index that describes the order of packets + that are received on a particular interface. + The packetID of a packet captured on an + interface is defined to be greater than the + packetID's of all packets captured previously on + the same interface. As the captureBufferPacketID + object has a maximum positive value of 2^31 - 1, + any captureBufferPacketID object shall have the + value of the associated packet's packetID mod 2^31." + ::= { captureBufferEntry 3 } + + captureBufferPacketData OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The data inside the packet, starting at the beginning + of the packet plus any offset specified in the + associated bufferControlDownloadOffset, including any + link level headers. The length of the data in this + object is the minimum of the length of the captured + packet minus the offset, the length of the associated + bufferControlCaptureSliceSize minus the offset, and the + associated bufferControlDownloadSliceSize. If this + minimum is less than zero, this object shall have a + length of zero." + ::= { captureBufferEntry 4 } + + captureBufferPacketLength OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The actual length (off the wire) of the packet stored + in this entry, including FCS octets." + ::= { captureBufferEntry 5 } + + captureBufferPacketTime OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of milliseconds that had passed since + this capture buffer was first turned on when this + packet was captured." + ::= { captureBufferEntry 6 } + + + captureBufferPacketStatus OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A value which indicates the error status of this + packet. + + The value of this object is defined in the same way as + filterPacketStatus. The value is a sum. This sum + initially takes the value zero. Then, for each + error, E, that has been discovered in this packet, + 2 raised to a value representing E is added to the sum. + + The errors defined for a packet captured off of an + Ethernet interface are as follows: + + bit # Error + 0 Packet is longer than 1518 octets + 1 Packet is shorter than 64 octets + 2 Packet experienced a CRC or Alignment + error + 3 First packet in this capture buffer after + it was detected that some packets were + not processed correctly. + + For example, an Ethernet fragment would have a + value of 6 (2^1 + 2^2). + + As this MIB is expanded to new media types, this object + will have other media-specific errors defined." + ::= { captureBufferEntry 7 } + + + -- The Event Group + + -- Implementation of the Event group is optional. + -- + -- The Event group controls the generation and notification + -- of events from this device. Each entry in the eventTable + -- describes the parameters of the event that can be triggered. + -- Each event entry is fired by an associated condition located + -- elsewhere in the MIB. An event entry may also be associated + -- with a function elsewhere in the MIB that will be executed + -- when the event is generated. For example, a channel may + -- be turned on or off by the firing of an event. + -- + -- Each eventEntry may optionally specify that a log entry + + + -- be created on its behalf whenever the event occurs. + -- Each entry may also specify that notification should + -- occur by way of SNMP trap messages. In this case, the + -- community for the trap message is given in the associated + -- eventCommunity object. The enterprise and specific trap + -- fields of the trap are determined by the condition that + -- triggered the event. Three traps are defined in a companion + -- document: risingAlarm, fallingAlarm, and packetMatch. + -- If the eventTable is triggered by a condition specified + -- elsewhere, the enterprise and specific trap fields + -- must be specified for traps generated for that condition. + + eventTable OBJECT-TYPE + SYNTAX SEQUENCE OF EventEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of events to be generated." + ::= { event 1 } + + eventEntry OBJECT-TYPE + SYNTAX EventEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of parameters that describe an event to be + generated when certain conditions are met." + INDEX { eventIndex } + ::= { eventTable 1 } + + EventEntry ::= SEQUENCE { + eventIndex INTEGER (1..65535), + eventDescription DisplayString (SIZE (0..127)), + eventType INTEGER, + eventCommunity OCTET STRING (SIZE (0..127)), + eventLastTimeSent TimeTicks, + eventOwner OwnerString, + eventStatus INTEGER + } + + eventIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + event table. Each such entry defines one event that + is to be generated when the appropriate conditions + + + occur." + ::= { eventEntry 1 } + + eventDescription OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..127)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A comment describing this event entry." + ::= { eventEntry 2 } + + eventType OBJECT-TYPE + SYNTAX INTEGER { + none(1), + log(2), + snmp-trap(3), -- send an SNMP trap + log-and-trap(4) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The type of notification that the probe will make + about this event. In the case of log, an entry is + made in the log table for each event. In the case of + snmp-trap, an SNMP trap is sent to one or more + management stations." + ::= { eventEntry 3 } + + eventCommunity OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..127)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "If an SNMP trap is to be sent, it will be sent to + the SNMP community specified by this octet string. + In the future this table will be extended to include + the party security mechanism. This object shall be + set to a string of length zero if it is intended that + that mechanism be used to specify the destination of + the trap." + ::= { eventEntry 4 } + + eventLastTimeSent OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the time this event + + + entry last generated an event. If this entry has + not generated any events, this value will be + zero." + ::= { eventEntry 5 } + + eventOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it. + + If this object contains a string starting with 'monitor' + and has associated entries in the log table, all + connected management stations should retrieve those + log entries, as they may have significance to all + management stations connected to this device" + ::= { eventEntry 6 } + + eventStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this event entry. + + If this object is not equal to valid(1), all associated + log entries shall be deleted by the agent." + ::= { eventEntry 7 } + + -- + logTable OBJECT-TYPE + SYNTAX SEQUENCE OF LogEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of events that have been logged." + ::= { event 2 } + + logEntry OBJECT-TYPE + SYNTAX LogEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of data describing an event that has been + logged." + INDEX { logEventIndex, logIndex } + + + ::= { logTable 1 } + + LogEntry ::= SEQUENCE { + logEventIndex INTEGER (1..65535), + logIndex INTEGER, + logTime TimeTicks, + logDescription DisplayString (SIZE (0..255)) + } + + logEventIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The event entry that generated this log + entry. The log identified by a particular + value of this index is associated with the same + eventEntry as identified by the same value + of eventIndex." + ::= { logEntry 1 } + + logIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the log table amongst those generated by the + same eventEntries. These indexes are + assigned beginning with 1 and increase by one + with each new log entry. The association + between values of logIndex and logEntries + is fixed for the lifetime of each logEntry. + The agent may choose to delete the oldest + instances of logEntry as required because of + lack of memory. It is an implementation-specific + matter as to when this deletion may occur." + ::= { logEntry 2 } + + logTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when this log entry was + created." + ::= { logEntry 3 } + + + + logDescription OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An implementation dependent description of the + event that activated this log entry." + ::= { logEntry 4 } + + END + diff --git a/lib/snmp/test/test-mibs/RMON-MIB.mib b/lib/snmp/test/test-mibs/RMON-MIB.mib new file mode 100644 index 0000000000..0824dbde1d --- /dev/null +++ b/lib/snmp/test/test-mibs/RMON-MIB.mib @@ -0,0 +1,3826 @@ + RMON-MIB DEFINITIONS ::= BEGIN + + IMPORTS + Counter FROM RFC1155-SMI + mib-2,DisplayString FROM RFC1213-MIB + OBJECT-TYPE FROM RFC-1212 + TRAP-TYPE FROM RFC-1215; + + -- Remote Network Monitoring MIB + + rmon OBJECT IDENTIFIER ::= { mib-2 16 } + + + -- textual conventions + + OwnerString ::= DisplayString + -- This data type is used to model an administratively + -- assigned name of the owner of a resource. This + -- information is taken from the NVT ASCII character + -- set. It is suggested that this name contain one or + + + -- more of the following: IP address, management station + -- name, network manager's name, location, or phone + -- number. + -- In some cases the agent itself will be the owner of + -- an entry. In these cases, this string shall be set + -- to a string starting with 'monitor'. + -- + -- SNMP access control is articulated entirely in terms + -- of the contents of MIB views; access to a particular + -- SNMP object instance depends only upon its presence + -- or absence in a particular MIB view and never upon + -- its value or the value of related object instances. + -- Thus, objects of this type afford resolution of + -- resource contention only among cooperating managers; + -- they realize no access control function with respect + -- to uncooperative parties. + -- + -- By convention, objects with this syntax are declared as + -- having + -- + -- SIZE (0..127) + + EntryStatus ::= INTEGER + { valid(1), + createRequest(2), + underCreation(3), + invalid(4) + } + -- The status of a table entry. + -- + -- Setting this object to the value invalid(4) has the + -- effect of invalidating the corresponding entry. + -- That is, it effectively disassociates the mapping + -- identified with said entry. + -- It is an implementation-specific matter as to whether + -- the agent removes an invalidated entry from the table. + -- Accordingly, management stations must be prepared to + -- receive tabular information from agents that + -- corresponds to entries currently not in use. Proper + -- interpretation of such entries requires examination + -- of the relevant EntryStatus object. + -- + -- An existing instance of this object cannot be set to + -- createRequest(2). This object may only be set to + -- createRequest(2) when this instance is created. When + -- this object is created, the agent may wish to create + -- supplemental object instances with default values + -- to complete a conceptual row in this table. Because + + + -- the creation of these default objects is entirely at + -- the option of the agent, the manager must not assume + -- that any will be created, but may make use of any that + -- are created. Immediately after completing the create + -- operation, the agent must set this object to + -- underCreation(3). + -- + -- When in the underCreation(3) state, an entry is + -- allowed to exist in a possibly incomplete, possibly + -- inconsistent state, usually to allow it to be + -- modified in mutiple PDUs. When in this state, an + -- entry is not fully active. Entries shall exist in + -- the underCreation(3) state until the management + -- station is finished configuring the entry and sets + -- this object to valid(1) or aborts, setting this + -- object to invalid(4). If the agent determines that + -- an entry has been in the underCreation(3) state for + -- an abnormally long time, it may decide that the + -- management station has crashed. If the agent makes + -- this decision, it may set this object to invalid(4) + -- to reclaim the entry. A prudent agent will + -- understand that the management station may need to + -- wait for human input and will allow for that + -- possibility in its determination of this abnormally + -- long period. + -- + -- An entry in the valid(1) state is fully configured and + -- consistent and fully represents the configuration or + -- operation such a row is intended to represent. For + -- example, it could be a statistical function that is + -- configured and active, or a filter that is available + -- in the list of filters processed by the packet capture + -- process. + -- + -- A manager is restricted to changing the state of an + -- entry in the following ways: + -- + -- create under + -- To: valid Request Creation invalid + -- From: + -- valid OK NO OK OK + -- createRequest N/A N/A N/A N/A + -- underCreation OK NO OK OK + -- invalid NO NO NO OK + -- nonExistent NO OK NO OK + -- + -- In the table above, it is not applicable to move the + -- state from the createRequest state to any other + + + -- state because the manager will never find the + -- variable in that state. The nonExistent state is + -- not a value of the enumeration, rather it means that + -- the entryStatus variable does not exist at all. + -- + -- An agent may allow an entryStatus variable to change + -- state in additional ways, so long as the semantics + -- of the states are followed. This allowance is made + -- to ease the implementation of the agent and is made + -- despite the fact that managers should never + -- excercise these additional state transitions. + + + statistics OBJECT IDENTIFIER ::= { rmon 1 } + history OBJECT IDENTIFIER ::= { rmon 2 } + alarm OBJECT IDENTIFIER ::= { rmon 3 } + hosts OBJECT IDENTIFIER ::= { rmon 4 } + hostTopN OBJECT IDENTIFIER ::= { rmon 5 } + matrix OBJECT IDENTIFIER ::= { rmon 6 } + filter OBJECT IDENTIFIER ::= { rmon 7 } + capture OBJECT IDENTIFIER ::= { rmon 8 } + event OBJECT IDENTIFIER ::= { rmon 9 } + + + -- The Ethernet Statistics Group + -- + -- Implementation of the Ethernet Statistics group is + -- optional. + -- + -- The ethernet statistics group contains statistics + -- measured by the probe for each monitored interface on + -- this device. These statistics take the form of free + -- running counters that start from zero when a valid entry + -- is created. + -- + -- This group currently has statistics defined only for + -- Ethernet interfaces. Each etherStatsEntry contains + -- statistics for one Ethernet interface. The probe must + -- create one etherStats entry for each monitored Ethernet + -- interface on the device. + + etherStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF EtherStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of Ethernet statistics entries." + ::= { statistics 1 } + + + etherStatsEntry OBJECT-TYPE + SYNTAX EtherStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics kept for a particular + Ethernet interface. As an example, an instance of the + etherStatsPkts object might be named etherStatsPkts.1" + INDEX { etherStatsIndex } + ::= { etherStatsTable 1 } + + EtherStatsEntry ::= SEQUENCE { + etherStatsIndex INTEGER (1..65535), + etherStatsDataSource OBJECT IDENTIFIER, + etherStatsDropEvents Counter, + etherStatsOctets Counter, + etherStatsPkts Counter, + etherStatsBroadcastPkts Counter, + etherStatsMulticastPkts Counter, + etherStatsCRCAlignErrors Counter, + etherStatsUndersizePkts Counter, + etherStatsOversizePkts Counter, + etherStatsFragments Counter, + etherStatsJabbers Counter, + etherStatsCollisions Counter, + etherStatsPkts64Octets Counter, + etherStatsPkts65to127Octets Counter, + etherStatsPkts128to255Octets Counter, + etherStatsPkts256to511Octets Counter, + etherStatsPkts512to1023Octets Counter, + etherStatsPkts1024to1518Octets Counter, + etherStatsOwner OwnerString, + etherStatsStatus EntryStatus + } + + etherStatsIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies this + etherStats entry." + ::= { etherStatsEntry 1 } + + etherStatsDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + + + DESCRIPTION + "This object identifies the source of the data that + this etherStats entry is configured to analyze. This + source can be any ethernet interface on this device. + In order to identify a particular interface, this + object shall identify the instance of the ifIndex + object, defined in RFC 1213 and RFC 1573 [4,6], for + the desired interface. For example, if an entry + were to receive data from interface #1, this object + would be set to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the + identified interface. + + An agent may or may not be able to tell if + fundamental changes to the media of the interface + have occurred and necessitate an invalidation of + this entry. For example, a hot-pluggable ethernet + card could be pulled out and replaced by a + token-ring card. In such a case, if the agent has + such knowledge of the change, it is recommended that + it invalidate this entry. + + This object may not be modified if the associated + etherStatsStatus object is equal to valid(1)." + ::= { etherStatsEntry 2 } + + etherStatsDropEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of events in which packets + were dropped by the probe due to lack of resources. + Note that this number is not necessarily the number of + packets dropped; it is just the number of times this + condition has been detected." + ::= { etherStatsEntry 3 } + + etherStatsOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets of data (including + those in bad packets) received on the + network (excluding framing bits but including + + + FCS octets). + + This object can be used as a reasonable estimate of + ethernet utilization. If greater precision is + desired, the etherStatsPkts and etherStatsOctets + objects should be sampled before and after a common + interval. The differences in the sampled values are + Pkts and Octets, respectively, and the number of + seconds in the interval is Interval. These values + are used to calculate the Utilization as follows: + + Pkts * (9.6 + 6.4) + (Octets * .8) + Utilization = ------------------------------------- + Interval * 10,000 + + The result of this equation is the value Utilization + which is the percent utilization of the ethernet + segment on a scale of 0 to 100 percent." + ::= { etherStatsEntry 4 } + + etherStatsPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including bad packets, + broadcast packets, and multicast packets) received." + ::= { etherStatsEntry 5 } + + etherStatsBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good packets received that were + directed to the broadcast address. Note that this + does not include multicast packets." + ::= { etherStatsEntry 6 } + + etherStatsMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good packets received that were + directed to a multicast address. Note that this + number does not include packets directed to the + broadcast address." + + + ::= { etherStatsEntry 7 } + + etherStatsCRCAlignErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received that + had a length (excluding framing bits, but + including FCS octets) of between 64 and 1518 + octets, inclusive, but but had either a bad + Frame Check Sequence (FCS) with an integral + number of octets (FCS Error) or a bad FCS with + a non-integral number of octets (Alignment Error)." + ::= { etherStatsEntry 8 } + + etherStatsUndersizePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received that were + less than 64 octets long (excluding framing bits, + but including FCS octets) and were otherwise well + formed." + ::= { etherStatsEntry 9 } + + etherStatsOversizePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received that were + longer than 1518 octets (excluding framing bits, + but including FCS octets) and were otherwise + well formed." + ::= { etherStatsEntry 10 } + + etherStatsFragments OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received that were less + than 64 octets in length (excluding framing bits but + including FCS octets) and had either a bad Frame + Check Sequence (FCS) with an integral number of + octets (FCS Error) or a bad FCS with a non-integral + + + number of octets (Alignment Error). + + Note that it is entirely normal for + etherStatsFragments to increment. This is because + it counts both runts (which are normal occurrences + due to collisions) and noise hits." + ::= { etherStatsEntry 11 } + + etherStatsJabbers OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received that were + longer than 1518 octets (excluding framing bits, + but including FCS octets), and had either a bad + Frame Check Sequence (FCS) with an integral number + of octets (FCS Error) or a bad FCS with a + non-integral number of octets (Alignment Error). + + Note that this definition of jabber is different + than the definition in IEEE-802.3 section 8.2.1.5 + (10BASE5) and section 10.3.1.4 (10BASE2). These + documents define jabber as the condition where any + packet exceeds 20 ms. The allowed range to detect + jabber is between 20 ms and 150 ms." + ::= { etherStatsEntry 12 } + + etherStatsCollisions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The best estimate of the total number of collisions + on this Ethernet segment. + + The value returned will depend on the location of + the RMON probe. Section 8.2.1.3 (10BASE-5) and + section 10.3.1.3 (10BASE-2) of IEEE standard 802.3 + states that a station must detect a collision, in + the receive mode, if three or more stations are + transmitting simultaneously. A repeater port must + detect a collision when two or more stations are + transmitting simultaneously. Thus a probe placed on + a repeater port could record more collisions than a + probe connected to a station on the same segment + would. + + + + Probe location plays a much smaller role when + considering 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE + standard 802.3 defines a collision as the + simultaneous presence of signals on the DO and RD + circuits (transmitting and receiving at the same + time). A 10BASE-T station can only detect + collisions when it is transmitting. Thus probes + placed on a station and a repeater, should report + the same number of collisions. + + Note also that an RMON probe inside a repeater + should ideally report collisions between the + repeater and one or more other hosts (transmit + collisions as defined by IEEE 802.3k) plus receiver + collisions observed on any coax segments to which + the repeater is connected." + ::= { etherStatsEntry 13 } + + etherStatsPkts64Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including bad + packets) received that were 64 octets in length + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 14 } + + etherStatsPkts65to127Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 65 and 127 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 15 } + + etherStatsPkts128to255Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 128 and 255 octets in length inclusive + (excluding framing bits but including FCS octets)." + + + ::= { etherStatsEntry 16 } + + etherStatsPkts256to511Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 256 and 511 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 17 } + + etherStatsPkts512to1023Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 512 and 1023 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 18 } + + etherStatsPkts1024to1518Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 1024 and 1518 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 19 } + + etherStatsOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { etherStatsEntry 20 } + + etherStatsStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + + + DESCRIPTION + "The status of this etherStats entry." + ::= { etherStatsEntry 21 } + + + -- The History Control Group + + -- Implementation of the History Control group is optional. + -- + -- The history control group controls the periodic statistical + -- sampling of data from various types of networks. The + -- historyControlTable stores configuration entries that each + -- define an interface, polling period, and other parameters. + -- Once samples are taken, their data is stored in an entry + -- in a media-specific table. Each such entry defines one + -- sample, and is associated with the historyControlEntry that + -- caused the sample to be taken. Each counter in the + -- etherHistoryEntry counts the same event as its + -- similarly-named counterpart in the etherStatsEntry, + -- except that each value here is a cumulative sum during a + -- sampling period. + -- + -- If the probe keeps track of the time of day, it should + -- start the first sample of the history at a time such that + -- when the next hour of the day begins, a sample is + -- started at that instant. This tends to make more + -- user-friendly reports, and enables comparison of reports + -- from different probes that have relatively accurate time + -- of day. + -- + -- The probe is encouraged to add two history control entries + -- per monitored interface upon initialization that describe + -- a short term and a long term polling period. Suggested + -- parameters are 30 seconds for the short term polling period + -- and 30 minutes for the long term period. + + historyControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HistoryControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of history control entries." + ::= { history 1 } + + historyControlEntry OBJECT-TYPE + SYNTAX HistoryControlEntry + ACCESS not-accessible + STATUS mandatory + + + DESCRIPTION + "A list of parameters that set up a periodic sampling + of statistics. As an example, an instance of the + historyControlInterval object might be named + historyControlInterval.2" + INDEX { historyControlIndex } + ::= { historyControlTable 1 } + + HistoryControlEntry ::= SEQUENCE { + historyControlIndex INTEGER (1..65535), + historyControlDataSource OBJECT IDENTIFIER, + historyControlBucketsRequested INTEGER (1..65535), + historyControlBucketsGranted INTEGER (1..65535), + historyControlInterval INTEGER (1..3600), + historyControlOwner OwnerString, + historyControlStatus EntryStatus + } + + historyControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + historyControl table. Each such entry defines a + set of samples at a particular interval for an + interface on the device." + ::= { historyControlEntry 1 } + + historyControlDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the source of the data for + which historical data was collected and + placed in a media-specific table on behalf of this + historyControlEntry. This source can be any + interface on this device. In order to identify + a particular interface, this object shall identify + the instance of the ifIndex object, defined + in RFC 1213 and RFC 1573 [4,6], for the desired + interface. For example, if an entry were to receive + data from interface #1, this object would be set + to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the + + + identified interface. + + An agent may or may not be able to tell if fundamental + changes to the media of the interface have occurred + and necessitate an invalidation of this entry. For + example, a hot-pluggable ethernet card could be + pulled out and replaced by a token-ring card. In + such a case, if the agent has such knowledge of the + change, it is recommended that it invalidate this + entry. + + This object may not be modified if the associated + historyControlStatus object is equal to valid(1)." + ::= { historyControlEntry 2 } + + historyControlBucketsRequested OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The requested number of discrete time intervals + over which data is to be saved in the part of the + media-specific table associated with this + historyControlEntry. + + When this object is created or modified, the probe + should set historyControlBucketsGranted as closely to + this object as is possible for the particular probe + implementation and available resources." + DEFVAL { 50 } + ::= { historyControlEntry 3 } + + historyControlBucketsGranted OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of discrete sampling intervals + over which data shall be saved in the part of + the media-specific table associated with this + historyControlEntry. + + When the associated historyControlBucketsRequested + object is created or modified, the probe + should set this object as closely to the requested + value as is possible for the particular + probe implementation and available resources. The + probe must not lower this value except as a result + + + of a modification to the associated + historyControlBucketsRequested object. + + There will be times when the actual number of + buckets associated with this entry is less than + the value of this object. In this case, at the + end of each sampling interval, a new bucket will + be added to the media-specific table. + + When the number of buckets reaches the value of + this object and a new bucket is to be added to the + media-specific table, the oldest bucket associated + with this historyControlEntry shall be deleted by + the agent so that the new bucket can be added. + + When the value of this object changes to a value less + than the current value, entries are deleted + from the media-specific table associated with this + historyControlEntry. Enough of the oldest of these + entries shall be deleted by the agent so that their + number remains less than or equal to the new value of + this object. + + When the value of this object changes to a value + greater than the current value, the number of + associated media- specific entries may be allowed to + grow." + ::= { historyControlEntry 4 } + + historyControlInterval OBJECT-TYPE + SYNTAX INTEGER (1..3600) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The interval in seconds over which the data is + sampled for each bucket in the part of the + media-specific table associated with this + historyControlEntry. This interval can + be set to any number of seconds between 1 and + 3600 (1 hour). + + Because the counters in a bucket may overflow at their + maximum value with no indication, a prudent manager + will take into account the possibility of overflow + in any of the associated counters. It is important + to consider the minimum time in which any counter + could overflow on a particular media type and set + the historyControlInterval object to a value less + + + than this interval. This is typically most + important for the 'octets' counter in any + media-specific table. For example, on an Ethernet + network, the etherHistoryOctets counter could + overflow in about one hour at the Ethernet's maximum + utilization. + + This object may not be modified if the associated + historyControlStatus object is equal to valid(1)." + DEFVAL { 1800 } + ::= { historyControlEntry 5 } + + historyControlOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { historyControlEntry 6 } + + historyControlStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this historyControl entry. + + Each instance of the media-specific table associated + with this historyControlEntry will be deleted by the + agent if this historyControlEntry is not equal to + valid(1)." + ::= { historyControlEntry 7 } + + + -- The Ethernet History Group + + -- Implementation of the Ethernet History group is optional. + -- + -- The Ethernet History group records periodic + -- statistical samples from a network and stores them + -- for later retrieval. Once samples are taken, their + -- data is stored in an entry in a media-specific + -- table. Each such entry defines one sample, and is + -- associated with the historyControlEntry that caused + -- the sample to be taken. This group defines the + -- etherHistoryTable, for Ethernet networks. + -- + + + etherHistoryTable OBJECT-TYPE + SYNTAX SEQUENCE OF EtherHistoryEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of Ethernet history entries." + ::= { history 2 } + + etherHistoryEntry OBJECT-TYPE + SYNTAX EtherHistoryEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "An historical sample of Ethernet statistics on a + particular Ethernet interface. This sample is + associated with the historyControlEntry which set up + the parameters for a regular collection of these + samples. As an example, an instance of the + etherHistoryPkts object might be named + etherHistoryPkts.2.89" + INDEX { etherHistoryIndex , etherHistorySampleIndex } + ::= { etherHistoryTable 1 } + + EtherHistoryEntry ::= SEQUENCE { + etherHistoryIndex INTEGER (1..65535), + etherHistorySampleIndex INTEGER (1..2147483647), + etherHistoryIntervalStart TimeTicks, + etherHistoryDropEvents Counter, + etherHistoryOctets Counter, + etherHistoryPkts Counter, + etherHistoryBroadcastPkts Counter, + etherHistoryMulticastPkts Counter, + etherHistoryCRCAlignErrors Counter, + etherHistoryUndersizePkts Counter, + etherHistoryOversizePkts Counter, + etherHistoryFragments Counter, + etherHistoryJabbers Counter, + etherHistoryCollisions Counter, + etherHistoryUtilization INTEGER (0..10000) + } + + etherHistoryIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The history of which this entry is a part. The + history identified by a particular value of this + + + index is the same history as identified + by the same value of historyControlIndex." + ::= { etherHistoryEntry 1 } + + etherHistorySampleIndex OBJECT-TYPE + SYNTAX INTEGER (1..2147483647) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies the particular + sample this entry represents among all samples + associated with the same historyControlEntry. + This index starts at 1 and increases by one + as each new sample is taken." + ::= { etherHistoryEntry 2 } + + etherHistoryIntervalStart OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the start of the interval + over which this sample was measured. If the probe + keeps track of the time of day, it should start + the first sample of the history at a time such that + when the next hour of the day begins, a sample is + started at that instant. Note that following this + rule may require the probe to delay collecting the + first sample of the history, as each sample must be + of the same interval. Also note that the sample which + is currently being collected is not accessible in this + table until the end of its interval." + ::= { etherHistoryEntry 3 } + + etherHistoryDropEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of events in which packets + were dropped by the probe due to lack of resources + during this sampling interval. Note that this number + is not necessarily the number of packets dropped, it + is just the number of times this condition has been + detected." + ::= { etherHistoryEntry 4 } + + etherHistoryOctets OBJECT-TYPE + + + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets of data (including + those in bad packets) received on the + network (excluding framing bits but including + FCS octets)." + ::= { etherHistoryEntry 5 } + + etherHistoryPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets (including bad packets) + received during this sampling interval." + ::= { etherHistoryEntry 6 } + + etherHistoryBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets received during this + sampling interval that were directed to the + broadcast address." + ::= { etherHistoryEntry 7 } + + etherHistoryMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets received during this + sampling interval that were directed to a + multicast address. Note that this number does not + include packets addressed to the broadcast address." + ::= { etherHistoryEntry 8 } + + etherHistoryCRCAlignErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received during this sampling + interval that had a length (excluding framing bits + but including FCS octets) between 64 and 1518 + + + octets, inclusive, but had either a bad Frame Check + Sequence (FCS) with an integral number of octets + (FCS Error) or a bad FCS with a non-integral number + of octets (Alignment Error)." + ::= { etherHistoryEntry 9 } + + etherHistoryUndersizePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received during this + sampling interval that were less than 64 octets + long (excluding framing bits but including FCS + octets) and were otherwise well formed." + ::= { etherHistoryEntry 10 } + + etherHistoryOversizePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received during this + sampling interval that were longer than 1518 + octets (excluding framing bits but including + FCS octets) but were otherwise well formed." + ::= { etherHistoryEntry 11 } + + etherHistoryFragments OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of packets received during this + sampling interval that were less than 64 octets in + length (excluding framing bits but including FCS + octets) had either a bad Frame Check Sequence (FCS) + with an integral number of octets (FCS Error) or a bad + FCS with a non-integral number of octets (Alignment + Error). + + Note that it is entirely normal for + etherHistoryFragments to increment. This is because + it counts both runts (which are normal occurrences + due to collisions) and noise hits." + ::= { etherHistoryEntry 12 } + + etherHistoryJabbers OBJECT-TYPE + + + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets received during this + sampling interval that were longer than 1518 octets + (excluding framing bits but including FCS octets), + and had either a bad Frame Check Sequence (FCS) + with an integral number of octets (FCS Error) or + a bad FCS with a non-integral number of octets + (Alignment Error). + + Note that this definition of jabber is different + than the definition in IEEE-802.3 section 8.2.1.5 + (10BASE5) and section 10.3.1.4 (10BASE2). These + documents define jabber as the condition where any + packet exceeds 20 ms. The allowed range to detect + jabber is between 20 ms and 150 ms." + ::= { etherHistoryEntry 13 } + + etherHistoryCollisions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The best estimate of the total number of collisions + on this Ethernet segment during this sampling + interval. + + The value returned will depend on the location of + the RMON probe. Section 8.2.1.3 (10BASE-5) and + section 10.3.1.3 (10BASE-2) of IEEE standard 802.3 + states that a station must detect a collision, in + the receive mode, if three or more stations are + transmitting simultaneously. A repeater port must + detect a collision when two or more stations are + transmitting simultaneously. Thus a probe placed on + a repeater port could record more collisions than a + probe connected to a station on the same segment + would. + + Probe location plays a much smaller role when + considering 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE + standard 802.3 defines a collision as the + simultaneous presence of signals on the DO and RD + circuits (transmitting and receiving at the same + time). A 10BASE-T station can only detect + collisions when it is transmitting. Thus probes + + + placed on a station and a repeater, should report + the same number of collisions. + + Note also that an RMON probe inside a repeater + should ideally report collisions between the + repeater and one or more other hosts (transmit + collisions as defined by IEEE 802.3k) plus receiver + collisions observed on any coax segments to which + the repeater is connected." + ::= { etherHistoryEntry 14 } + + etherHistoryUtilization OBJECT-TYPE + SYNTAX INTEGER (0..10000) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The best estimate of the mean physical layer + network utilization on this interface during this + sampling interval, in hundredths of a percent." + ::= { etherHistoryEntry 15 } + + + -- The Alarm Group + + -- Implementation of the Alarm group is optional. + -- + -- The Alarm Group requires the implementation of the Event + -- group. + -- + -- The Alarm group periodically takes + -- statistical samples from variables in the probe and + -- compares them to thresholds that have been + -- configured. The alarm table stores configuration + -- entries that each define a variable, polling period, + -- and threshold parameters. If a sample is found to + -- cross the threshold values, an event is generated. + -- Only variables that resolve to an ASN.1 primitive + -- type of INTEGER (INTEGER, Counter, Gauge, or + -- TimeTicks) may be monitored in this way. + -- + -- This function has a hysteresis mechanism to limit + -- the generation of events. This mechanism generates + -- one event as a threshold is crossed in the + -- appropriate direction. No more events are generated + -- for that threshold until the opposite threshold is + -- crossed. + -- + -- In the case of a sampling a deltaValue, a probe may + + + -- implement this mechanism with more precision if it + -- takes a delta sample twice per period, each time + -- comparing the sum of the latest two samples to the + -- threshold. This allows the detection of threshold + -- crossings that span the sampling boundary. Note + -- that this does not require any special configuration + -- of the threshold value. It is suggested that probes + -- implement this more precise algorithm. + + alarmTable OBJECT-TYPE + SYNTAX SEQUENCE OF AlarmEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of alarm entries." + ::= { alarm 1 } + + alarmEntry OBJECT-TYPE + SYNTAX AlarmEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of parameters that set up a periodic checking + for alarm conditions. For example, an instance of the + alarmValue object might be named alarmValue.8" + INDEX { alarmIndex } + ::= { alarmTable 1 } + + AlarmEntry ::= SEQUENCE { + alarmIndex INTEGER (1..65535), + alarmInterval INTEGER, + alarmVariable OBJECT IDENTIFIER, + alarmSampleType INTEGER, + alarmValue INTEGER, + alarmStartupAlarm INTEGER, + alarmRisingThreshold INTEGER, + alarmFallingThreshold INTEGER, + alarmRisingEventIndex INTEGER (0..65535), + alarmFallingEventIndex INTEGER (0..65535), + alarmOwner OwnerString, + alarmStatus EntryStatus + } + + alarmIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + + + "An index that uniquely identifies an entry in the + alarm table. Each such entry defines a + diagnostic sample at a particular interval + for an object on the device." + ::= { alarmEntry 1 } + + alarmInterval OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The interval in seconds over which the data is + sampled and compared with the rising and falling + thresholds. When setting this variable, care + should be taken in the case of deltaValue + sampling - the interval should be set short enough + that the sampled variable is very unlikely to + increase or decrease by more than 2^31 - 1 during + a single sampling interval. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 2 } + + alarmVariable OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The object identifier of the particular variable to + be sampled. Only variables that resolve to an ASN.1 + primitive type of INTEGER (INTEGER, Counter, Gauge, + or TimeTicks) may be sampled. + + Because SNMP access control is articulated entirely + in terms of the contents of MIB views, no access + control mechanism exists that can restrict the value + of this object to identify only those objects that + exist in a particular MIB view. Because there is + thus no acceptable means of restricting the read + access that could be obtained through the alarm + mechanism, the probe must only grant write access to + this object in those views that have read access to + all objects on the probe. + + During a set operation, if the supplied variable + name is not available in the selected MIB view, a + badValue error must be returned. If at any time the + + + variable name of an established alarmEntry is no + longer available in the selected MIB view, the probe + must change the status of this alarmEntry to + invalid(4). + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 3 } + + alarmSampleType OBJECT-TYPE + SYNTAX INTEGER { + absoluteValue(1), + deltaValue(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The method of sampling the selected variable and + calculating the value to be compared against the + thresholds. If the value of this object is + absoluteValue(1), the value of the selected variable + will be compared directly with the thresholds at the + end of the sampling interval. If the value of this + object is deltaValue(2), the value of the selected + variable at the last sample will be subtracted from + the current value, and the difference compared with + the thresholds. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 4 } + + alarmValue OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of the statistic during the last sampling + period. For example, if the sample type is + deltaValue, this value will be the difference + between the samples at the beginning and end of the + period. If the sample type is absoluteValue, this + value will be the sampled value at the end of the + period. + + This is the value that is compared with the rising and + falling thresholds. + + + + The value during the current sampling period is not + made available until the period is completed and will + remain available until the next period completes." + ::= { alarmEntry 5 } + + alarmStartupAlarm OBJECT-TYPE + SYNTAX INTEGER { + risingAlarm(1), + fallingAlarm(2), + risingOrFallingAlarm(3) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The alarm that may be sent when this entry is first + set to valid. If the first sample after this entry + becomes valid is greater than or equal to the + risingThreshold and alarmStartupAlarm is equal to + risingAlarm(1) or risingOrFallingAlarm(3), then a + single rising alarm will be generated. If the first + sample after this entry becomes valid is less than + or equal to the fallingThreshold and + alarmStartupAlarm is equal to fallingAlarm(2) or + risingOrFallingAlarm(3), then a single falling alarm + will be generated. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 6 } + + alarmRisingThreshold OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A threshold for the sampled statistic. When the + current sampled value is greater than or equal to + this threshold, and the value at the last sampling + interval was less than this threshold, a single + event will be generated. A single event will also + be generated if the first sample after this entry + becomes valid is greater than or equal to this + threshold and the associated alarmStartupAlarm is + equal to risingAlarm(1) or risingOrFallingAlarm(3). + + After a rising event is generated, another such event + will not be generated until the sampled value + falls below this threshold and reaches the + + + alarmFallingThreshold. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 7 } + + alarmFallingThreshold OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A threshold for the sampled statistic. When the + current sampled value is less than or equal to this + threshold, and the value at the last sampling + interval was greater than this threshold, a single + event will be generated. A single event will also + be generated if the first sample after this entry + becomes valid is less than or equal to this + threshold and the associated alarmStartupAlarm is + equal to fallingAlarm(2) or risingOrFallingAlarm(3). + + After a falling event is generated, another such event + will not be generated until the sampled value + rises above this threshold and reaches the + alarmRisingThreshold. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 8 } + + alarmRisingEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The index of the eventEntry that is + used when a rising threshold is crossed. The + eventEntry identified by a particular value of + this index is the same as identified by the same value + of the eventIndex object. If there is no + corresponding entry in the eventTable, then + no association exists. In particular, if this value + is zero, no associated event will be generated, as + zero is not a valid event index. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 9 } + + + alarmFallingEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The index of the eventEntry that is + used when a falling threshold is crossed. The + eventEntry identified by a particular value of + this index is the same as identified by the same value + of the eventIndex object. If there is no + corresponding entry in the eventTable, then + no association exists. In particular, if this value + is zero, no associated event will be generated, as + zero is not a valid event index. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 10 } + + alarmOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { alarmEntry 11 } + + alarmStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this alarm entry." + ::= { alarmEntry 12 } + + + -- The Host Group + + -- Implementation of the Host group is optional. + -- + -- The host group discovers new hosts on the network by + -- keeping a list of source and destination MAC Addresses seen + -- in good packets. For each of these addresses, the host + -- group keeps a set of statistics. The hostControlTable + -- controls which interfaces this function is performed on, + -- and contains some information about the process. On + -- behalf of each hostControlEntry, data is collected on an + + + -- interface and placed in both the hostTable and the + -- hostTimeTable. If the monitoring device finds itself + -- short of resources, it may delete entries as needed. It + -- is suggested that the device delete the least recently + -- used entries first. + + -- The hostTable contains entries for each address + -- discovered on a particular interface. Each entry + -- contains statistical data about that host. This table is + -- indexed by the MAC address of the host, through which a + -- random access may be achieved. + + -- The hostTimeTable contains data in the same format as the + -- hostTable, and must contain the same set of hosts, but is + -- indexed using hostTimeCreationOrder rather than + -- hostAddress. + -- The hostTimeCreationOrder is an integer which reflects + -- the relative order in which a particular entry was + -- discovered and thus inserted into the table. As this + -- order, and thus the index, is among those entries + -- currently in the table, the index for a particular entry + -- may change if an (earlier) entry is deleted. Thus the + -- association between hostTimeCreationOrder and + -- hostTimeEntry may be broken at any time. + + -- The hostTimeTable has two important uses. The first is the + -- fast download of this potentially large table. Because the + -- index of this table runs from 1 to the size of the table, + -- inclusive, its values are predictable. This allows very + -- efficient packing of variables into SNMP PDU's and allows + -- a table transfer to have multiple packets outstanding. + -- These benefits increase transfer rates tremendously. + + -- The second use of the hostTimeTable is the efficient + -- discovery by the management station of new entries added + -- to the table. After the management station has downloaded + -- the entire table, it knows that new entries will be added + -- immediately after the end of the current table. It can + -- thus detect new entries there and retrieve them easily. + + -- Because the association between hostTimeCreationOrder and + -- hostTimeEntry may be broken at any time, the management + -- station must monitor the related hostControlLastDeleteTime + -- object. When the management station thus detects a + -- deletion, it must assume that any such associations have + --- been broken, and invalidate any it has stored locally. + -- This includes restarting any download of the + -- hostTimeTable that may have been in progress, as well as + + + -- rediscovering the end of the hostTimeTable so that it may + -- detect new entries. If the management station does not + -- detect the broken association, it may continue to refer + -- to a particular host by its creationOrder while + -- unwittingly retrieving the data associated with another + -- host entirely. If this happens while downloading the + -- host table, the management station may fail to download + -- all of the entries in the table. + + hostControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of host table control entries." + ::= { hosts 1 } + + hostControlEntry OBJECT-TYPE + SYNTAX HostControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of parameters that set up the discovery of + hosts on a particular interface and the collection + of statistics about these hosts. For example, an + instance of the hostControlTableSize object might be + named hostControlTableSize.1" + INDEX { hostControlIndex } + ::= { hostControlTable 1 } + + HostControlEntry ::= SEQUENCE { + hostControlIndex INTEGER (1..65535), + hostControlDataSource OBJECT IDENTIFIER, + hostControlTableSize INTEGER, + hostControlLastDeleteTime TimeTicks, + hostControlOwner OwnerString, + hostControlStatus EntryStatus + } + + hostControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + hostControl table. Each such entry defines + a function that discovers hosts on a particular + interface and places statistics about them in the + + + hostTable and the hostTimeTable on behalf of this + hostControlEntry." + ::= { hostControlEntry 1 } + + hostControlDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the source of the data for + this instance of the host function. This source + can be any interface on this device. In order + to identify a particular interface, this object shall + identify the instance of the ifIndex object, defined + in RFC 1213 and RFC 1573 [4,6], for the desired + interface. For example, if an entry were to receive + data from interface #1, this object would be set to + ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the + identified interface. + + An agent may or may not be able to tell if + fundamental changes to the media of the interface + have occurred and necessitate an invalidation of + this entry. For example, a hot-pluggable ethernet + card could be pulled out and replaced by a + token-ring card. In such a case, if the agent has + such knowledge of the change, it is recommended that + it invalidate this entry. + + This object may not be modified if the associated + hostControlStatus object is equal to valid(1)." + ::= { hostControlEntry 2 } + + hostControlTableSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of hostEntries in the hostTable and the + hostTimeTable associated with this hostControlEntry." + ::= { hostControlEntry 3 } + + hostControlLastDeleteTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + + + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when the last entry + was deleted from the portion of the hostTable + associated with this hostControlEntry. If no + deletions have occurred, this value shall be zero." + ::= { hostControlEntry 4 } + + hostControlOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { hostControlEntry 5 } + + hostControlStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this hostControl entry. + + If this object is not equal to valid(1), all + associated entries in the hostTable, hostTimeTable, + and the hostTopNTable shall be deleted by the + agent." + ::= { hostControlEntry 6 } + + hostTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of host entries." + ::= { hosts 2 } + + hostEntry OBJECT-TYPE + SYNTAX HostEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for a particular host + that has been discovered on an interface of this + device. For example, an instance of the + hostOutBroadcastPkts object might be named + hostOutBroadcastPkts.1.6.8.0.32.27.3.176" + + + INDEX { hostIndex, hostAddress } + ::= { hostTable 1 } + + HostEntry ::= SEQUENCE { + hostAddress OCTET STRING, + hostCreationOrder INTEGER (1..65535), + hostIndex INTEGER (1..65535), + hostInPkts Counter, + hostOutPkts Counter, + hostInOctets Counter, + hostOutOctets Counter, + hostOutErrors Counter, + hostOutBroadcastPkts Counter, + hostOutMulticastPkts Counter + } + + hostAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The physical address of this host." + ::= { hostEntry 1 } + + hostCreationOrder OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that defines the relative ordering of + the creation time of hosts captured for a + particular hostControlEntry. This index shall + be between 1 and N, where N is the value of + the associated hostControlTableSize. The ordering + of the indexes is based on the order of each entry's + insertion into the table, in which entries added + earlier have a lower index value than entries added + later. + + It is important to note that the order for a + particular entry may change as an (earlier) entry + is deleted from the table. Because this order may + change, management stations should make use of the + hostControlLastDeleteTime variable in the + hostControlEntry associated with the relevant + portion of the hostTable. By observing + this variable, the management station may detect + the circumstances where a previous association + + + between a value of hostCreationOrder + and a hostEntry may no longer hold." + ::= { hostEntry 2 } + + hostIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The set of collected host statistics of which + this entry is a part. The set of hosts + identified by a particular value of this + index is associated with the hostControlEntry + as identified by the same value of hostControlIndex." + ::= { hostEntry 3 } + + hostInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets transmitted to this + address since it was added to the hostTable." + ::= { hostEntry 4 } + + hostOutPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets, including bad packets, + transmitted by this address since it was added + to the hostTable." + ::= { hostEntry 5 } + + hostInOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets transmitted to this address + since it was added to the hostTable (excluding + framing bits but including FCS octets), except for + those octets in bad packets." + ::= { hostEntry 6 } + + hostOutOctets OBJECT-TYPE + SYNTAX Counter + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets transmitted by this address + since it was added to the hostTable (excluding + framing bits but including FCS octets), including + those octets in bad packets." + ::= { hostEntry 7 } + + hostOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of bad packets transmitted by this address + since this host was added to the hostTable." + ::= { hostEntry 8 } + + hostOutBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to the broadcast address + since this host was added to the hostTable." + ::= { hostEntry 9 } + + hostOutMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to a multicast address + since this host was added to the hostTable. + Note that this number does not include packets + directed to the broadcast address." + ::= { hostEntry 10 } + + -- host Time Table + + hostTimeTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostTimeEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of time-ordered host table entries." + + + ::= { hosts 3 } + + hostTimeEntry OBJECT-TYPE + SYNTAX HostTimeEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for a particular host + that has been discovered on an interface of this + device. This collection includes the relative + ordering of the creation time of this object. For + example, an instance of the hostTimeOutBroadcastPkts + object might be named + hostTimeOutBroadcastPkts.1.687" + INDEX { hostTimeIndex, hostTimeCreationOrder } + ::= { hostTimeTable 1 } + + HostTimeEntry ::= SEQUENCE { + hostTimeAddress OCTET STRING, + hostTimeCreationOrder INTEGER (1..65535), + hostTimeIndex INTEGER (1..65535), + hostTimeInPkts Counter, + hostTimeOutPkts Counter, + hostTimeInOctets Counter, + hostTimeOutOctets Counter, + hostTimeOutErrors Counter, + hostTimeOutBroadcastPkts Counter, + hostTimeOutMulticastPkts Counter + } + + hostTimeAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The physical address of this host." + ::= { hostTimeEntry 1 } + + hostTimeCreationOrder OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in + the hostTime table among those entries associated + with the same hostControlEntry. This index shall + be between 1 and N, where N is the value of + the associated hostControlTableSize. The ordering + + + of the indexes is based on the order of each entry's + insertion into the table, in which entries added + earlier have a lower index value than entries added + later. Thus the management station has the ability to + learn of new entries added to this table without + downloading the entire table. + + It is important to note that the index for a + particular entry may change as an (earlier) entry + is deleted from the table. Because this order may + change, management stations should make use of the + hostControlLastDeleteTime variable in the + hostControlEntry associated with the relevant + portion of the hostTimeTable. By observing + this variable, the management station may detect + the circumstances where a download of the table + may have missed entries, and where a previous + association between a value of hostTimeCreationOrder + and a hostTimeEntry may no longer hold." + ::= { hostTimeEntry 2 } + + hostTimeIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The set of collected host statistics of which + this entry is a part. The set of hosts + identified by a particular value of this + index is associated with the hostControlEntry + as identified by the same value of hostControlIndex." + ::= { hostTimeEntry 3 } + + hostTimeInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets transmitted to this + address since it was added to the hostTimeTable." + ::= { hostTimeEntry 4 } + + hostTimeOutPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of god packets transmitted by this + + + address since it was added to the hostTimeTable." + ::= { hostTimeEntry 5 } + + hostTimeInOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets transmitted to this address + since it was added to the hostTimeTable (excluding + framing bits but including FCS octets), except for + those octets in bad packets." + ::= { hostTimeEntry 6 } + + hostTimeOutOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets transmitted by this address + since it was added to the hostTimeTable (excluding + framing bits but including FCS octets), including + those octets in bad packets." + ::= { hostTimeEntry 7 } + + hostTimeOutErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of bad packets transmitted by this address + since this host was added to the hostTimeTable." + ::= { hostTimeEntry 8 } + + hostTimeOutBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to the broadcast address + since this host was added to the hostTimeTable." + ::= { hostTimeEntry 9 } + + hostTimeOutMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to a multicast address + since this host was added to the hostTimeTable. + Note that this number does not include packets + directed to the broadcast address." + ::= { hostTimeEntry 10 } + + + -- The Host Top "N" Group + + -- Implementation of the Host Top N group is optional. + -- + -- The Host Top N group requires the implementation of the + -- host group. + -- + -- The Host Top N group is used to prepare reports that + -- describe the hosts that top a list ordered by one of + -- their statistics. + -- The available statistics are samples of one of their + -- base statistics, over an interval specified by the + -- management station. Thus, these statistics are rate + -- based. The management station also selects how many such + -- hosts are reported. + + -- The hostTopNControlTable is used to initiate the + -- generation of such a report. The management station + -- may select the parameters of such a report, such as + -- which interface, which statistic, how many hosts, + -- and the start and stop times of the sampling. When + -- the report is prepared, entries are created in the + -- hostTopNTable associated with the relevant + -- hostTopNControlEntry. These entries are static for + -- each report after it has been prepared. + + hostTopNControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostTopNControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of top N host control entries." + ::= { hostTopN 1 } + + hostTopNControlEntry OBJECT-TYPE + SYNTAX HostTopNControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + + + "A set of parameters that control the creation of a + report of the top N hosts according to several + metrics. For example, an instance of the + hostTopNDuration object might be named + hostTopNDuration.3" + INDEX { hostTopNControlIndex } + ::= { hostTopNControlTable 1 } + + HostTopNControlEntry ::= SEQUENCE { + hostTopNControlIndex INTEGER (1..65535), + hostTopNHostIndex INTEGER (1..65535), + hostTopNRateBase INTEGER, + hostTopNTimeRemaining INTEGER, + hostTopNDuration INTEGER, + hostTopNRequestedSize INTEGER, + hostTopNGrantedSize INTEGER, + hostTopNStartTime TimeTicks, + hostTopNOwner OwnerString, + hostTopNStatus EntryStatus + } + + hostTopNControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the hostTopNControl table. Each such + entry defines one top N report prepared for + one interface." + ::= { hostTopNControlEntry 1 } + + hostTopNHostIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The host table for which a top N report will be + prepared on behalf of this entry. The host table + identified by a particular value of this index is + associated with the same host table as identified by + the same value of hostIndex. + + This object may not be modified if the associated + hostTopNStatus object is equal to valid(1)." + ::= { hostTopNControlEntry 2 } + + hostTopNRateBase OBJECT-TYPE + + + SYNTAX INTEGER { + hostTopNInPkts(1), + hostTopNOutPkts(2), + hostTopNInOctets(3), + hostTopNOutOctets(4), + hostTopNOutErrors(5), + hostTopNOutBroadcastPkts(6), + hostTopNOutMulticastPkts(7) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The variable for each host that the hostTopNRate + variable is based upon. + + This object may not be modified if the associated + hostTopNStatus object is equal to valid(1)." + ::= { hostTopNControlEntry 3 } + + hostTopNTimeRemaining OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The number of seconds left in the report currently + being collected. When this object is modified by + the management station, a new collection is started, + possibly aborting a currently running report. The + new value is used as the requested duration of this + report, which is loaded into the associated + hostTopNDuration object. + + When this object is set to a non-zero value, any + associated hostTopNEntries shall be made + inaccessible by the monitor. While the value of + this object is non-zero, it decrements by one per + second until it reaches zero. During this time, all + associated hostTopNEntries shall remain + inaccessible. At the time that this object + decrements to zero, the report is made accessible in + the hostTopNTable. Thus, the hostTopN table needs + to be created only at the end of the collection + interval." + DEFVAL { 0 } + ::= { hostTopNControlEntry 4 } + + hostTopNDuration OBJECT-TYPE + SYNTAX INTEGER + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of seconds that this report has collected + during the last sampling interval, or if this + report is currently being collected, the number + of seconds that this report is being collected + during this sampling interval. + + When the associated hostTopNTimeRemaining object is + set, this object shall be set by the probe to the + same value and shall not be modified until the next + time the hostTopNTimeRemaining is set. + + This value shall be zero if no reports have been + requested for this hostTopNControlEntry." + DEFVAL { 0 } + ::= { hostTopNControlEntry 5 } + + hostTopNRequestedSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The maximum number of hosts requested for the top N + table. + + When this object is created or modified, the probe + should set hostTopNGrantedSize as closely to this + object as is possible for the particular probe + implementation and available resources." + DEFVAL { 10 } + ::= { hostTopNControlEntry 6 } + + hostTopNGrantedSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum number of hosts in the top N table. + + When the associated hostTopNRequestedSize object is + created or modified, the probe should set this + object as closely to the requested value as is + possible for the particular implementation and + available resources. The probe must not lower this + value except as a result of a set to the associated + hostTopNRequestedSize object. + + + Hosts with the highest value of hostTopNRate shall be + placed in this table in decreasing order of this rate + until there is no more room or until there are no more + hosts." + ::= { hostTopNControlEntry 7 } + + hostTopNStartTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when this top N report was + last started. In other words, this is the time that + the associated hostTopNTimeRemaining object was + modified to start the requested report." + ::= { hostTopNControlEntry 8 } + + hostTopNOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { hostTopNControlEntry 9 } + + hostTopNStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this hostTopNControl entry. + + If this object is not equal to valid(1), all + associated hostTopNEntries shall be deleted by the + agent." + ::= { hostTopNControlEntry 10 } + + hostTopNTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostTopNEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of top N host entries." + ::= { hostTopN 2 } + + hostTopNEntry OBJECT-TYPE + SYNTAX HostTopNEntry + + + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of statistics for a host that is part of a + top N report. For example, an instance of the + hostTopNRate object might be named + hostTopNRate.3.10" + INDEX { hostTopNReport, hostTopNIndex } + ::= { hostTopNTable 1 } + + HostTopNEntry ::= SEQUENCE { + hostTopNReport INTEGER (1..65535), + hostTopNIndex INTEGER (1..65535), + hostTopNAddress OCTET STRING, + hostTopNRate INTEGER + } + + hostTopNReport OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "This object identifies the top N report of which + this entry is a part. The set of hosts + identified by a particular value of this + object is part of the same report as identified + by the same value of the hostTopNControlIndex object." + ::= { hostTopNEntry 1 } + + hostTopNIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in + the hostTopN table among those in the same report. + This index is between 1 and N, where N is the + number of entries in this table. Increasing values + of hostTopNIndex shall be assigned to entries with + decreasing values of hostTopNRate until index N + is assigned to the entry with the lowest value of + hostTopNRate or there are no more hostTopNEntries." + ::= { hostTopNEntry 2 } + + hostTopNAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + + + DESCRIPTION + "The physical address of this host." + ::= { hostTopNEntry 3 } + + hostTopNRate OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The amount of change in the selected variable + during this sampling interval. The selected + variable is this host's instance of the object + selected by hostTopNRateBase." + ::= { hostTopNEntry 4 } + + + -- The Matrix Group + + -- Implementation of the Matrix group is optional. + -- + -- The Matrix group consists of the matrixControlTable, + -- matrixSDTable and the matrixDSTable. These tables + -- store statistics for a particular conversation + -- between two addresses. As the device detects a new + -- conversation, including those to a non-unicast + -- address, it creates a new entry in both of the + -- matrix tables. It must only create new entries + -- based on information received in good packets. If + -- the monitoring device finds itself short of + -- resources, it may delete entries as needed. It is + -- suggested that the device delete the least recently + -- used entries first. + + matrixControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of information entries for the + traffic matrix on each interface." + ::= { matrix 1 } + + matrixControlEntry OBJECT-TYPE + SYNTAX MatrixControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "Information about a traffic matrix on a particular + + + interface. For example, an instance of the + matrixControlLastDeleteTime object might be named + matrixControlLastDeleteTime.1" + INDEX { matrixControlIndex } + ::= { matrixControlTable 1 } + + MatrixControlEntry ::= SEQUENCE { + matrixControlIndex INTEGER (1..65535), + matrixControlDataSource OBJECT IDENTIFIER, + matrixControlTableSize INTEGER, + matrixControlLastDeleteTime TimeTicks, + matrixControlOwner OwnerString, + matrixControlStatus EntryStatus + } + + matrixControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + matrixControl table. Each such entry defines + a function that discovers conversations on a + particular interface and places statistics about + them in the matrixSDTable and the matrixDSTable on + behalf of this matrixControlEntry." + ::= { matrixControlEntry 1 } + + matrixControlDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the source of + the data from which this entry creates a traffic + matrix. This source can be any interface on this + device. In order to identify a particular + interface, this object shall identify the instance + of the ifIndex object, defined in RFC 1213 and RFC + 1573 [4,6], for the desired interface. For example, + if an entry were to receive data from interface #1, + this object would be set to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the + identified interface. + + An agent may or may not be able to tell if + + + fundamental changes to the media of the interface + have occurred and necessitate an invalidation of + this entry. For example, a hot-pluggable ethernet + card could be pulled out and replaced by a + token-ring card. In such a case, if the agent has + such knowledge of the change, it is recommended that + it invalidate this entry. + + This object may not be modified if the associated + matrixControlStatus object is equal to valid(1)." + ::= { matrixControlEntry 2 } + + matrixControlTableSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of matrixSDEntries in the matrixSDTable + for this interface. This must also be the value of + the number of entries in the matrixDSTable for this + interface." + ::= { matrixControlEntry 3 } + + matrixControlLastDeleteTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when the last entry + was deleted from the portion of the matrixSDTable + or matrixDSTable associated with this + matrixControlEntry. If no deletions have occurred, + this value shall be zero." + ::= { matrixControlEntry 4 } + + matrixControlOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { matrixControlEntry 5 } + + matrixControlStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + + + DESCRIPTION + "The status of this matrixControl entry. + + If this object is not equal to valid(1), all + associated entries in the matrixSDTable and the + matrixDSTable shall be deleted by the agent." + ::= { matrixControlEntry 6 } + + matrixSDTable OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixSDEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of traffic matrix entries indexed by + source and destination MAC address." + ::= { matrix 2 } + + matrixSDEntry OBJECT-TYPE + SYNTAX MatrixSDEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for communications between + two addresses on a particular interface. For example, + an instance of the matrixSDPkts object might be named + matrixSDPkts.1.6.8.0.32.27.3.176.6.8.0.32.10.8.113" + INDEX { matrixSDIndex, + matrixSDSourceAddress, matrixSDDestAddress } + ::= { matrixSDTable 1 } + + MatrixSDEntry ::= SEQUENCE { + matrixSDSourceAddress OCTET STRING, + matrixSDDestAddress OCTET STRING, + matrixSDIndex INTEGER (1..65535), + matrixSDPkts Counter, + matrixSDOctets Counter, + matrixSDErrors Counter + } + + matrixSDSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The source physical address." + ::= { matrixSDEntry 1 } + + matrixSDDestAddress OBJECT-TYPE + + + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The destination physical address." + ::= { matrixSDEntry 2 } + + matrixSDIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The set of collected matrix statistics of which + this entry is a part. The set of matrix statistics + identified by a particular value of this index + is associated with the same matrixControlEntry + as identified by the same value of + matrixControlIndex." + ::= { matrixSDEntry 3 } + + matrixSDPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets transmitted from the source + address to the destination address (this number + includes bad packets)." + ::= { matrixSDEntry 4 } + + matrixSDOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets (excluding framing bits but + including FCS octets) contained in all packets + transmitted from the source address to the + destination address." + ::= { matrixSDEntry 5 } + + matrixSDErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of bad packets transmitted from + the source address to the destination address." + + + ::= { matrixSDEntry 6 } + + + -- Traffic matrix tables from destination to source + + matrixDSTable OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixDSEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of traffic matrix entries indexed by + destination and source MAC address." + ::= { matrix 3 } + + matrixDSEntry OBJECT-TYPE + SYNTAX MatrixDSEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for communications between + two addresses on a particular interface. For example, + an instance of the matrixSDPkts object might be named + matrixSDPkts.1.6.8.0.32.10.8.113.6.8.0.32.27.3.176" + INDEX { matrixDSIndex, + matrixDSDestAddress, matrixDSSourceAddress } + ::= { matrixDSTable 1 } + + MatrixDSEntry ::= SEQUENCE { + matrixDSSourceAddress OCTET STRING, + matrixDSDestAddress OCTET STRING, + matrixDSIndex INTEGER (1..65535), + matrixDSPkts Counter, + matrixDSOctets Counter, + matrixDSErrors Counter + } + + matrixDSSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The source physical address." + ::= { matrixDSEntry 1 } + + matrixDSDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + + + DESCRIPTION + "The destination physical address." + ::= { matrixDSEntry 2 } + + matrixDSIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The set of collected matrix statistics of which + this entry is a part. The set of matrix statistics + identified by a particular value of this index + is associated with the same matrixControlEntry + as identified by the same value of + matrixControlIndex." + ::= { matrixDSEntry 3 } + + matrixDSPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets transmitted from the source + address to the destination address (this number + includes bad packets)." + ::= { matrixDSEntry 4 } + + matrixDSOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of octets (excluding framing bits + but including FCS octets) contained in all packets + transmitted from the source address to the + destination address." + ::= { matrixDSEntry 5 } + + matrixDSErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of bad packets transmitted from + the source address to the destination address." + ::= { matrixDSEntry 6 } + + + + + -- The Filter Group + + -- Implementation of the Filter group is optional. + -- + -- The Filter group allows packets to be captured with an + -- arbitrary filter expression. A logical data and + -- event stream or "channel" is formed by the packets + -- that match the filter expression. + -- + -- This filter mechanism allows the creation of an arbitrary + -- logical expression with which to filter packets. Each + -- filter associated with a channel is OR'ed with the others. + -- Within a filter, any bits checked in the data and status + -- are AND'ed with respect to other bits in the same filter. + -- The NotMask also allows for checking for inequality. + -- Finally, the channelAcceptType object allows for + -- inversion of the whole equation. + -- + -- If a management station wishes to receive a trap to alert + -- it that new packets have been captured and are available + -- for download, it is recommended that it set up an alarm + -- entry that monitors the value of the relevant + -- channelMatches instance. + -- + -- The channel can be turned on or off, and can also + -- generate events when packets pass through it. + + filterTable OBJECT-TYPE + SYNTAX SEQUENCE OF FilterEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of packet filter entries." + ::= { filter 1 } + + filterEntry OBJECT-TYPE + SYNTAX FilterEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of parameters for a packet filter applied on a + particular interface. As an example, an instance of + the filterPktData object might be named + filterPktData.12" + INDEX { filterIndex } + ::= { filterTable 1 } + + + + + FilterEntry ::= SEQUENCE { + filterIndex INTEGER (1..65535), + filterChannelIndex INTEGER (1..65535), + filterPktDataOffset INTEGER, + filterPktData OCTET STRING, + filterPktDataMask OCTET STRING, + filterPktDataNotMask OCTET STRING, + filterPktStatus INTEGER, + filterPktStatusMask INTEGER, + filterPktStatusNotMask INTEGER, + filterOwner OwnerString, + filterStatus EntryStatus + } + + filterIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the filter table. Each such entry defines + one filter that is to be applied to every packet + received on an interface." + ::= { filterEntry 1 } + + filterChannelIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the channel of which this + filter is a part. The filters identified by a + particular value of this object are associated with + the same channel as identified by the same value of + the channelIndex object." + ::= { filterEntry 2 } + + filterPktDataOffset OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The offset from the beginning of each packet where + a match of packet data will be attempted. This offset + is measured from the point in the physical layer + packet after the framing bits, if any. For example, + in an Ethernet frame, this point is at the beginning + of the destination MAC address. + + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + DEFVAL { 0 } + ::= { filterEntry 3 } + + filterPktData OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The data that is to be matched with the input + packet. For each packet received, this filter and + the accompanying filterPktDataMask and + filterPktDataNotMask will be adjusted for the + offset. The only bits relevant to this match + algorithm are those that have the corresponding + filterPktDataMask bit equal to one. The following + three rules are then applied to every packet: + + (1) If the packet is too short and does not have data + corresponding to part of the filterPktData, the + packet will fail this data match. + + (2) For each relevant bit from the packet with the + corresponding filterPktDataNotMask bit set to + zero, if the bit from the packet is not equal to + the corresponding bit from the filterPktData, + then the packet will fail this data match. + + (3) If for every relevant bit from the packet with the + corresponding filterPktDataNotMask bit set to one, + the bit from the packet is equal to the + corresponding bit from the filterPktData, then + the packet will fail this data match. + + Any packets that have not failed any of the three + matches above have passed this data match. In + particular, a zero length filter will match any + packet. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 4 } + + filterPktDataMask OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-write + STATUS mandatory + + + DESCRIPTION + "The mask that is applied to the match process. + After adjusting this mask for the offset, only those + bits in the received packet that correspond to bits + set in this mask are relevant for further processing + by the match algorithm. The offset is applied to + filterPktDataMask in the same way it is applied to the + filter. For the purposes of the matching algorithm, + if the associated filterPktData object is longer + than this mask, this mask is conceptually extended + with '1' bits until it reaches the length of the + filterPktData object. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 5 } + + filterPktDataNotMask OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The inversion mask that is applied to the match + process. After adjusting this mask for the offset, + those relevant bits in the received packet that + correspond to bits cleared in this mask must all be + equal to their corresponding bits in the + filterPktData object for the packet to be accepted. + In addition, at least one of those relevant bits in + the received packet that correspond to bits set in + this mask must be different to its corresponding bit + in the filterPktData object. + + For the purposes of the matching algorithm, if the + associated filterPktData object is longer than this + mask, this mask is conceptually extended with '0' + bits until it reaches the length of the + filterPktData object. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 6 } + + filterPktStatus OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + + + "The status that is to be matched with the input + packet. The only bits relevant to this match + algorithm are those that have the corresponding + filterPktStatusMask bit equal to one. The following + two rules are then applied to every packet: + + (1) For each relevant bit from the packet status + with the corresponding filterPktStatusNotMask bit + set to zero, if the bit from the packet status is + not equal to the corresponding bit from the + filterPktStatus, then the packet will fail this + status match. + + (2) If for every relevant bit from the packet status + with the corresponding filterPktStatusNotMask bit + set to one, the bit from the packet status is + equal to the corresponding bit from the + filterPktStatus, then the packet will fail this + status match. + + Any packets that have not failed either of the two + matches above have passed this status match. In + particular, a zero length status filter will match any + packet's status. + + The value of the packet status is a sum. This sum + initially takes the value zero. Then, for each + error, E, that has been discovered in this packet, + 2 raised to a value representing E is added to the + sum. The errors and the bits that represent them are + dependent on the media type of the interface that + this channel is receiving packets from. + + The errors defined for a packet captured off of an + Ethernet interface are as follows: + + bit # Error + 0 Packet is longer than 1518 octets + 1 Packet is shorter than 64 octets + 2 Packet experienced a CRC or Alignment + error + + For example, an Ethernet fragment would have a + value of 6 (2^1 + 2^2). + + As this MIB is expanded to new media types, this + object will have other media-specific errors + defined. + + + For the purposes of this status matching algorithm, + if the packet status is longer than this + filterPktStatus object, this object is conceptually + extended with '0' bits until it reaches the size of + the packet status. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 7 } + + filterPktStatusMask OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The mask that is applied to the status match + process. Only those bits in the received packet + that correspond to bits set in this mask are + relevant for further processing by the status match + algorithm. For the purposes of the matching + algorithm, if the associated filterPktStatus object + is longer than this mask, this mask is conceptually + extended with '1' bits until it reaches the size of + the filterPktStatus. In addition, if a packet + status is longer than this mask, this mask is + conceptually extended with '0' bits until it reaches + the size of the packet status. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 8 } + + filterPktStatusNotMask OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The inversion mask that is applied to the status + match process. Those relevant bits in the received + packet status that correspond to bits cleared in + this mask must all be equal to their corresponding + bits in the filterPktStatus object for the packet to + be accepted. In addition, at least one of those + relevant bits in the received packet status that + correspond to bits set in this mask must be + different to its corresponding bit in the + filterPktStatus object for the packet to be + accepted. + + + For the purposes of the matching algorithm, if the + associated filterPktStatus object or a packet status + is longer than this mask, this mask is conceptually + extended with '0' bits until it reaches the longer + of the lengths of the filterPktStatus object and the + packet status. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 9 } + + filterOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { filterEntry 10 } + + filterStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this filter entry." + ::= { filterEntry 11 } + + channelTable OBJECT-TYPE + SYNTAX SEQUENCE OF ChannelEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of packet channel entries." + ::= { filter 2 } + + channelEntry OBJECT-TYPE + SYNTAX ChannelEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of parameters for a packet channel applied on a + particular interface. As an example, an instance of + the channelMatches object might be named + channelMatches.3" + INDEX { channelIndex } + ::= { channelTable 1 } + + + + ChannelEntry ::= SEQUENCE { + channelIndex INTEGER (1..65535), + channelIfIndex INTEGER (1..65535), + channelAcceptType INTEGER, + channelDataControl INTEGER, + channelTurnOnEventIndex INTEGER (0..65535), + channelTurnOffEventIndex INTEGER (0..65535), + channelEventIndex INTEGER (0..65535), + channelEventStatus INTEGER, + channelMatches Counter, + channelDescription DisplayString (SIZE (0..127)), + channelOwner OwnerString, + channelStatus EntryStatus + } + + channelIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + channel table. Each such entry defines one channel, + a logical data and event stream. + + It is suggested that before creating a channel, an + application should scan all instances of the + filterChannelIndex object to make sure that there + are no pre-existing filters that would be + inadvertently be linked to the channel." + ::= { channelEntry 1 } + + channelIfIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies the + interface on this remote network monitoring device + to which the associated filters are applied to allow + data into this channel. The interface identified by + a particular value of this object is the same + interface as identified by the same value of the + ifIndex object, defined in RFC 1213 and RFC 1573 + [4,6]. + + The filters in this group are applied to all packets + on the local network segment attached to the + identified interface. + + + An agent may or may not be able to tell if + fundamental changes to the media of the interface + have occurred and necessitate an invalidation of + this entry. For example, a hot-pluggable ethernet + card could be pulled out and replaced by a + token-ring card. In such a case, if the agent has + such knowledge of the change, it is recommended that + it invalidate this entry. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 2 } + + channelAcceptType OBJECT-TYPE + SYNTAX INTEGER { + acceptMatched(1), + acceptFailed(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object controls the action of the filters + associated with this channel. If this object is equal + to acceptMatched(1), packets will be accepted to this + channel if they are accepted by both the packet data + and packet status matches of an associated filter. If + this object is equal to acceptFailed(2), packets will + be accepted to this channel only if they fail either + the packet data match or the packet status match of + each of the associated filters. + + In particular, a channel with no associated filters + will match no packets if set to acceptMatched(1) + case and will match all packets in the + acceptFailed(2) case. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 3 } + + channelDataControl OBJECT-TYPE + SYNTAX INTEGER { + on(1), + off(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + + + "This object controls the flow of data through this + channel. If this object is on(1), data, status and + events flow through this channel. If this object is + off(2), data, status and events will not flow + through this channel." + DEFVAL { off } + ::= { channelEntry 4 } + + channelTurnOnEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The value of this object identifies the event + that is configured to turn the associated + channelDataControl from off to on when the event is + generated. The event identified by a particular value + of this object is the same event as identified by the + same value of the eventIndex object. If there is no + corresponding entry in the eventTable, then no + association exists. In fact, if no event is intended + for this channel, channelTurnOnEventIndex must be + set to zero, a non-existent event index. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 5 } + + channelTurnOffEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The value of this object identifies the event + that is configured to turn the associated + channelDataControl from on to off when the event is + generated. The event identified by a particular value + of this object is the same event as identified by the + same value of the eventIndex object. If there is no + corresponding entry in the eventTable, then no + association exists. In fact, if no event is intended + for this channel, channelTurnOffEventIndex must be + set to zero, a non-existent event index. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 6 } + + + + channelEventIndex OBJECT-TYPE + SYNTAX INTEGER (0..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The value of this object identifies the event + that is configured to be generated when the + associated channelDataControl is on and a packet + is matched. The event identified by a particular + value of this object is the same event as identified + by the same value of the eventIndex object. If + there is no corresponding entry in the eventTable, + then no association exists. In fact, if no event is + intended for this channel, channelEventIndex must be + set to zero, a non-existent event index. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 7 } + + channelEventStatus OBJECT-TYPE + SYNTAX INTEGER { + eventReady(1), + eventFired(2), + eventAlwaysReady(3) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The event status of this channel. + + If this channel is configured to generate events + when packets are matched, a means of controlling + the flow of those events is often needed. When + this object is equal to eventReady(1), a single + event may be generated, after which this object + will be set by the probe to eventFired(2). While + in the eventFired(2) state, no events will be + generated until the object is modified to + eventReady(1) (or eventAlwaysReady(3)). The + management station can thus easily respond to a + notification of an event by re-enabling this object. + + If the management station wishes to disable this + flow control and allow events to be generated + at will, this object may be set to + eventAlwaysReady(3). Disabling the flow control + is discouraged as it can result in high network + + + traffic or other performance problems." + DEFVAL { eventReady } + ::= { channelEntry 8 } + + channelMatches OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times this channel has matched a + packet. Note that this object is updated even when + channelDataControl is set to off." + ::= { channelEntry 9 } + + channelDescription OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..127)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A comment describing this channel." + ::= { channelEntry 10 } + + channelOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { channelEntry 11 } + + channelStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this channel entry." + ::= { channelEntry 12 } + + + -- The Packet Capture Group + + -- Implementation of the Packet Capture group is optional. + -- + -- The Packet Capture Group requires implementation of the + -- Filter Group. + -- + -- The Packet Capture group allows packets to be captured + + + -- upon a filter match. The bufferControlTable controls + -- the captured packets output from a channel that is + -- associated with it. The captured packets are placed + -- in entries in the captureBufferTable. These entries are + -- associated with the bufferControlEntry on whose behalf they + -- were stored. + + bufferControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF BufferControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of buffers control entries." + ::= { capture 1 } + + bufferControlEntry OBJECT-TYPE + SYNTAX BufferControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of parameters that control the collection of + a stream of packets that have matched filters. As + an example, an instance of the + bufferControlCaptureSliceSize object might be named + bufferControlCaptureSliceSize.3" + INDEX { bufferControlIndex } + ::= { bufferControlTable 1 } + + BufferControlEntry ::= SEQUENCE { + bufferControlIndex INTEGER (1..65535), + bufferControlChannelIndex INTEGER (1..65535), + bufferControlFullStatus INTEGER, + bufferControlFullAction INTEGER, + bufferControlCaptureSliceSize INTEGER, + bufferControlDownloadSliceSize INTEGER, + bufferControlDownloadOffset INTEGER, + bufferControlMaxOctetsRequested INTEGER, + bufferControlMaxOctetsGranted INTEGER, + bufferControlCapturedPackets INTEGER, + bufferControlTurnOnTime TimeTicks, + bufferControlOwner OwnerString, + bufferControlStatus EntryStatus + } + + bufferControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + + + DESCRIPTION + "An index that uniquely identifies an entry + in the bufferControl table. The value of this + index shall never be zero. Each such + entry defines one set of packets that is + captured and controlled by one or more filters." + ::= { bufferControlEntry 1 } + + bufferControlChannelIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An index that identifies the channel that is the + source of packets for this bufferControl table. + The channel identified by a particular value of this + index is the same as identified by the same value of + the channelIndex object. + + This object may not be modified if the associated + bufferControlStatus object is equal to valid(1)." + ::= { bufferControlEntry 2 } + + bufferControlFullStatus OBJECT-TYPE + SYNTAX INTEGER { + spaceAvailable(1), + full(2) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "This object shows whether the buffer has room to + accept new packets or if it is full. + + If the status is spaceAvailable(1), the buffer is + accepting new packets normally. If the status is + full(2) and the associated bufferControlFullAction + object is wrapWhenFull, the buffer is accepting new + packets by deleting enough of the oldest packets + to make room for new ones as they arrive. Otherwise, + if the status is full(2) and the + bufferControlFullAction object is lockWhenFull, + then the buffer has stopped collecting packets. + + When this object is set to full(2) the probe must + not later set it to spaceAvailable(1) except in the + case of a significant gain in resources such as + an increase of bufferControlOctetsGranted. In + + + particular, the wrap-mode action of deleting old + packets to make room for newly arrived packets + must not affect the value of this object." + ::= { bufferControlEntry 3 } + + bufferControlFullAction OBJECT-TYPE + SYNTAX INTEGER { + lockWhenFull(1), + wrapWhenFull(2) -- FIFO + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Controls the action of the buffer when it + reaches the full status. When in the lockWhenFull(1) + state and a packet is added to the buffer that + fills the buffer, the bufferControlFullStatus will + be set to full(2) and this buffer will stop capturing + packets." + ::= { bufferControlEntry 4 } + + bufferControlCaptureSliceSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The maximum number of octets of each packet + that will be saved in this capture buffer. + For example, if a 1500 octet packet is received by + the probe and this object is set to 500, then only + 500 octets of the packet will be stored in the + associated capture buffer. If this variable is set + to 0, the capture buffer will save as many octets + as is possible. + + This object may not be modified if the associated + bufferControlStatus object is equal to valid(1)." + DEFVAL { 100 } + ::= { bufferControlEntry 5 } + + bufferControlDownloadSliceSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The maximum number of octets of each packet + in this capture buffer that will be returned in + an SNMP retrieval of that packet. For example, + + + if 500 octets of a packet have been stored in the + associated capture buffer, the associated + bufferControlDownloadOffset is 0, and this + object is set to 100, then the captureBufferPacket + object that contains the packet will contain only + the first 100 octets of the packet. + + A prudent manager will take into account possible + interoperability or fragmentation problems that may + occur if the download slice size is set too large. + In particular, conformant SNMP implementations are not + required to accept messages whose length exceeds 484 + octets, although they are encouraged to support larger + datagrams whenever feasible." + DEFVAL { 100 } + ::= { bufferControlEntry 6 } + + bufferControlDownloadOffset OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The offset of the first octet of each packet + in this capture buffer that will be returned in + an SNMP retrieval of that packet. For example, + if 500 octets of a packet have been stored in the + associated capture buffer and this object is set to + 100, then the captureBufferPacket object that + contains the packet will contain bytes starting + 100 octets into the packet." + DEFVAL { 0 } + ::= { bufferControlEntry 7 } + + bufferControlMaxOctetsRequested OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The requested maximum number of octets to be + saved in this captureBuffer, including any + implementation-specific overhead. If this variable + is set to -1, the capture buffer will save as many + octets as is possible. + + When this object is created or modified, the probe + should set bufferControlMaxOctetsGranted as closely + to this object as is possible for the particular probe + implementation and available resources. However, if + + + the object has the special value of -1, the probe + must set bufferControlMaxOctetsGranted to -1." + DEFVAL { -1 } + ::= { bufferControlEntry 8 } + + bufferControlMaxOctetsGranted OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum number of octets that can be + saved in this captureBuffer, including overhead. + If this variable is -1, the capture buffer will save + as many octets as possible. + + When the bufferControlMaxOctetsRequested object is + created or modified, the probe should set this object + as closely to the requested value as is possible for + the particular probe implementation and available + resources. + However, if the request object has the special value + of -1, the probe must set this object to -1. + The probe must not lower this value except as a result + of a modification to the associated + bufferControlMaxOctetsRequested object. + + When this maximum number of octets is reached + and a new packet is to be added to this + capture buffer and the corresponding + bufferControlFullAction is set to wrapWhenFull(2), + enough of the oldest packets associated with this + capture buffer shall be deleted by the agent so + that the new packet can be added. If the + corresponding bufferControlFullAction is set to + lockWhenFull(1), the new packet shall be discarded. + In either case, the probe must set + bufferControlFullStatus to full(2). + + When the value of this object changes to a value less + than the current value, entries are deleted from + the captureBufferTable associated with this + bufferControlEntry. Enough of the + oldest of these captureBufferEntries shall be + deleted by the agent so that the number of octets + used remains less than or equal to the new value of + this object. + + When the value of this object changes to a value + + + greater than the current value, the number of + associated captureBufferEntries may be allowed to + grow." + ::= { bufferControlEntry 9 } + + bufferControlCapturedPackets OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of packets currently in this + captureBuffer." + ::= { bufferControlEntry 10 } + + bufferControlTurnOnTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when this capture buffer was + first turned on." + ::= { bufferControlEntry 11 } + + bufferControlOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { bufferControlEntry 12 } + + bufferControlStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this buffer Control Entry." + ::= { bufferControlEntry 13 } + + captureBufferTable OBJECT-TYPE + SYNTAX SEQUENCE OF CaptureBufferEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of packets captured off of a channel." + ::= { capture 2 } + + + + captureBufferEntry OBJECT-TYPE + SYNTAX CaptureBufferEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A packet captured off of an attached network. As an + example, an instance of the captureBufferPacketData + object might be named captureBufferPacketData.3.1783" + INDEX { captureBufferControlIndex, captureBufferIndex } + ::= { captureBufferTable 1 } + + CaptureBufferEntry ::= SEQUENCE { + captureBufferControlIndex INTEGER (1..65535), + captureBufferIndex INTEGER (1..2147483647), + captureBufferPacketID INTEGER, + captureBufferPacketData OCTET STRING, + captureBufferPacketLength INTEGER, + captureBufferPacketTime INTEGER, + captureBufferPacketStatus INTEGER + } + + captureBufferControlIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The index of the bufferControlEntry with which + this packet is associated." + ::= { captureBufferEntry 1 } + + captureBufferIndex OBJECT-TYPE + SYNTAX INTEGER (1..2147483647) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the captureBuffer table associated with a + particular bufferControlEntry. This index will + start at 1 and increase by one for each new packet + added with the same captureBufferControlIndex. + + Should this value reach 2147483647, the next packet + added with the same captureBufferControlIndex shall + cause this value to wrap around to 1." + ::= { captureBufferEntry 2 } + + captureBufferPacketID OBJECT-TYPE + SYNTAX INTEGER + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that describes the order of packets + that are received on a particular interface. + The packetID of a packet captured on an + interface is defined to be greater than the + packetID's of all packets captured previously on + the same interface. As the captureBufferPacketID + object has a maximum positive value of 2^31 - 1, + any captureBufferPacketID object shall have the + value of the associated packet's packetID mod 2^31." + ::= { captureBufferEntry 3 } + + captureBufferPacketData OBJECT-TYPE + SYNTAX OCTET STRING + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The data inside the packet, starting at the + beginning of the packet plus any offset specified in + the associated bufferControlDownloadOffset, + including any link level headers. The length of the + data in this object is the minimum of the length of + the captured packet minus the offset, the length of + the associated bufferControlCaptureSliceSize minus + the offset, and the associated + bufferControlDownloadSliceSize. If this minimum is + less than zero, this object shall have a length of + zero." + ::= { captureBufferEntry 4 } + + captureBufferPacketLength OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The actual length (off the wire) of the packet stored + in this entry, including FCS octets." + ::= { captureBufferEntry 5 } + + captureBufferPacketTime OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of milliseconds that had passed since + this capture buffer was first turned on when this + + + packet was captured." + ::= { captureBufferEntry 6 } + + captureBufferPacketStatus OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A value which indicates the error status of this + packet. + + The value of this object is defined in the same way as + filterPktStatus. The value is a sum. This sum + initially takes the value zero. Then, for each + error, E, that has been discovered in this packet, + 2 raised to a value representing E is added to the + sum. + + The errors defined for a packet captured off of an + Ethernet interface are as follows: + + bit # Error + 0 Packet is longer than 1518 octets + 1 Packet is shorter than 64 octets + 2 Packet experienced a CRC or Alignment + error + 3 First packet in this capture buffer after + it was detected that some packets were + not processed correctly. + 4 Packet's order in buffer is only + approximate (May only be set for packets + sent from the probe) + + For example, an Ethernet fragment would have a + value of 6 (2^1 + 2^2). + + As this MIB is expanded to new media types, this + object will have other media-specific errors defined." + ::= { captureBufferEntry 7 } + + + -- The Event Group + + -- Implementation of the Event group is optional. + -- + -- The Event group controls the generation and notification + -- of events from this device. Each entry in the eventTable + -- describes the parameters of the event that can be + + + -- triggered. Each event entry is fired by an associated + -- condition located elsewhere in the MIB. An event entry + -- may also be associated- with a function elsewhere in the + -- MIB that will be executed when the event is generated. For + -- example, a channel may be turned on or off by the firing + -- of an event. + -- + -- Each eventEntry may optionally specify that a log entry + -- be created on its behalf whenever the event occurs. + -- Each entry may also specify that notification should + -- occur by way of SNMP trap messages. In this case, the + -- community for the trap message is given in the associated + -- eventCommunity object. The enterprise and specific trap + -- fields of the trap are determined by the condition that + -- triggered the event. Two traps are defined: risingAlarm + -- and fallingAlarm. If the eventTable is triggered by a + -- condition specified elsewhere, the enterprise and + -- specific trap fields must be specified for traps + -- generated for that condition. + + eventTable OBJECT-TYPE + SYNTAX SEQUENCE OF EventEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of events to be generated." + ::= { event 1 } + + eventEntry OBJECT-TYPE + SYNTAX EventEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of parameters that describe an event to be + generated when certain conditions are met. As an + example, an instance of the eventLastTimeSent object + might be named eventLastTimeSent.6" + INDEX { eventIndex } + ::= { eventTable 1 } + + EventEntry ::= SEQUENCE { + eventIndex INTEGER (1..65535), + eventDescription DisplayString (SIZE (0..127)), + eventType INTEGER, + eventCommunity OCTET STRING (SIZE (0..127)), + eventLastTimeSent TimeTicks, + eventOwner OwnerString, + eventStatus EntryStatus + + + } + + eventIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry in the + event table. Each such entry defines one event that + is to be generated when the appropriate conditions + occur." + ::= { eventEntry 1 } + + eventDescription OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..127)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "A comment describing this event entry." + ::= { eventEntry 2 } + + eventType OBJECT-TYPE + SYNTAX INTEGER { + none(1), + log(2), + snmp-trap(3), -- send an SNMP trap + log-and-trap(4) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The type of notification that the probe will make + about this event. In the case of log, an entry is + made in the log table for each event. In the case of + snmp-trap, an SNMP trap is sent to one or more + management stations." + ::= { eventEntry 3 } + + eventCommunity OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..127)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "If an SNMP trap is to be sent, it will be sent to + the SNMP community specified by this octet string. + In the future this table will be extended to include + the party security mechanism. This object shall be + set to a string of length zero if it is intended that + + + that mechanism be used to specify the destination of + the trap." + ::= { eventEntry 4 } + + eventLastTimeSent OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the time this event + entry last generated an event. If this entry has + not generated any events, this value will be + zero." + ::= { eventEntry 5 } + + eventOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it. + + If this object contains a string starting with + 'monitor' and has associated entries in the log + table, all connected management stations should + retrieve those log entries, as they may have + significance to all management stations connected to + this device" + ::= { eventEntry 6 } + + eventStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this event entry. + + If this object is not equal to valid(1), all + associated log entries shall be deleted by the + agent." + ::= { eventEntry 7 } + + -- + logTable OBJECT-TYPE + SYNTAX SEQUENCE OF LogEntry + ACCESS not-accessible + STATUS mandatory + + + DESCRIPTION + "A list of events that have been logged." + ::= { event 2 } + + logEntry OBJECT-TYPE + SYNTAX LogEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A set of data describing an event that has been + logged. For example, an instance of the + logDescription object might be named + logDescription.6.47" + INDEX { logEventIndex, logIndex } + ::= { logTable 1 } + + LogEntry ::= SEQUENCE { + logEventIndex INTEGER (1..65535), + logIndex INTEGER (1..2147483647), + logTime TimeTicks, + logDescription DisplayString (SIZE (0..255)) + } + + logEventIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The event entry that generated this log + entry. The log identified by a particular + value of this index is associated with the same + eventEntry as identified by the same value + of eventIndex." + ::= { logEntry 1 } + + logIndex OBJECT-TYPE + SYNTAX INTEGER (1..2147483647) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies an entry + in the log table amongst those generated by the + same eventEntries. These indexes are + assigned beginning with 1 and increase by one + with each new log entry. The association + between values of logIndex and logEntries + is fixed for the lifetime of each logEntry. + The agent may choose to delete the oldest + + + instances of logEntry as required because of + lack of memory. It is an implementation-specific + matter as to when this deletion may occur." + ::= { logEntry 2 } + + logTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime when this log entry was + created." + ::= { logEntry 3 } + + logDescription OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An implementation dependent description of the + event that activated this log entry." + ::= { logEntry 4 } + + -- These definitions use the TRAP-TYPE macro as + -- defined in RFC 1215 [10] + + -- Remote Network Monitoring Traps + + risingAlarm TRAP-TYPE + ENTERPRISE rmon + VARIABLES { alarmIndex, alarmVariable, alarmSampleType, + alarmValue, alarmRisingThreshold } + DESCRIPTION + "The SNMP trap that is generated when an alarm + entry crosses its rising threshold and generates + an event that is configured for sending SNMP + traps." + ::= 1 + + fallingAlarm TRAP-TYPE + ENTERPRISE rmon + VARIABLES { alarmIndex, alarmVariable, alarmSampleType, + alarmValue, alarmFallingThreshold } + DESCRIPTION + "The SNMP trap that is generated when an alarm + entry crosses its falling threshold and generates + an event that is configured for sending SNMP + traps." + + + ::= 2 + + END + diff --git a/lib/snmp/test/test-mibs/RMON2-MIB.mib b/lib/snmp/test/test-mibs/RMON2-MIB.mib new file mode 100644 index 0000000000..827bb38ff9 --- /dev/null +++ b/lib/snmp/test/test-mibs/RMON2-MIB.mib @@ -0,0 +1,5450 @@ +RMON2-MIB DEFINITIONS ::= BEGIN +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Counter32, Integer32, + Gauge32, IpAddress, TimeTicks FROM SNMPv2-SMI + TEXTUAL-CONVENTION, RowStatus, DisplayString, TimeStamp + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP FROM SNMPv2-CONF + mib-2, ifIndex FROM RFC1213-MIB + OwnerString, statistics, history, hosts, + matrix, filter, etherStatsEntry, historyControlEntry, + hostControlEntry, matrixControlEntry, filterEntry, + channelEntry FROM RMON-MIB + tokenRing, tokenRingMLStatsEntry, tokenRingPStatsEntry, + ringStationControlEntry, sourceRoutingStatsEntry + FROM TOKEN-RING-RMON-MIB; +-- Remote Network Monitoring MIB + +rmon MODULE-IDENTITY + LAST-UPDATED "9605270000Z" + ORGANIZATION "IETF RMON MIB Working Group" + CONTACT-INFO + "Steve Waldbusser (WG Editor) + Postal: International Network Services + 650 Castro Street, Suite 260 + Mountain View, CA 94041 + Phone: +1 415 254 4251 + Email: [email protected] + + + Andy Bierman (WG Chair) + Phone: +1 805 648 2028 + Email: [email protected]" + DESCRIPTION + "The MIB module for managing remote monitoring + device implementations. This MIB module + augments the original RMON MIB as specified in + RFC 1757." + ::= { mib-2 16 } + +-- { rmon 1 } through { rmon 10 } are defined in RMON and +-- the Token Ring RMON MIB [RFC 1513] + + protocolDir OBJECT IDENTIFIER ::= { rmon 11 } + protocolDist OBJECT IDENTIFIER ::= { rmon 12 } + addressMap OBJECT IDENTIFIER ::= { rmon 13 } + nlHost OBJECT IDENTIFIER ::= { rmon 14 } + nlMatrix OBJECT IDENTIFIER ::= { rmon 15 } + alHost OBJECT IDENTIFIER ::= { rmon 16 } + alMatrix OBJECT IDENTIFIER ::= { rmon 17 } + usrHistory OBJECT IDENTIFIER ::= { rmon 18 } + probeConfig OBJECT IDENTIFIER ::= { rmon 19 } + rmonConformance OBJECT IDENTIFIER ::= { rmon 20 } + +-- Textual Conventions + +ZeroBasedCounter32 ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "This TC describes an object which counts events with the + following semantics: objects of this type will be set to + zero(0) on creation and will thereafter count appropriate + events, wrapping back to zero(0) when the value 2^32 is + reached. + + Provided that an application discovers the new object within + the minimum time to wrap it can use the initial value as a + delta since it last polled the table of which this object is + part. It is important for a management station to be aware of + this minimum time and the actual time between polls, and to + discard data if the actual time is too long or there is no + defined minimum time. + + Typically this TC is used in tables where the INDEX space is + constantly changing and/or the TimeFilter mechanism is in use." + SYNTAX Gauge32 + +LastCreateTime ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "This TC describes an object that stores the last time its + entry was created. + + This can be used for polling applications to determine that an + entry has been deleted and re-created between polls, causing + an otherwise undetectable discontinuity in the data." + SYNTAX TimeStamp + +TimeFilter ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + + + + "To be used for the index to a table. Allows an application + to download only those rows changed since a particular time. + A row is considered changed if the value of any object in the + row changes or if the row is created or deleted. + + When sysUpTime is equal to zero, this table shall be empty. + + One entry exists for each past value of sysUpTime, except that + the whole table is purged should sysUpTime wrap. + + As this basic row is updated new conceptual rows are created + (which still share the now updated object values with all + other instances). The number of instances which are created + is determined by the value of sysUpTime at which the basic row + was last updated. One instance will exist for each value of + sysUpTime at the last update time for the row. A new + timeMark instance is created for each new sysUpTime value. + Each new conceptual row will be associated with the timeMark + instance which was created at the value of sysUpTime with + which the conceptual row is to be associated. + + By definition all conceptual rows were updated at or after + time zero and so at least one conceptual row (associated with + timeMark.0) must exist for each underlying (basic) row. + + See the appendix for further discussion of this variable. + + Consider the following fooTable: + + fooTable ... + INDEX { fooTimeMark, fooIndex } + + FooEntry { + fooTimeMark TimeFilter + fooIndex INTEGER, + fooCounts Counter + } + + Should there be two basic rows in this table (fooIndex == 1, + fooIndex == 2) and row 1 was updated most recently at time 6, + while row 2 was updated most recently at time 8, and both rows + had been updated on several earlier occasions such that the + current values were 5 and 9 respectively then the following + fooCounts instances would exist. + + fooCounts.0.1 5 + fooCounts.0.2 9 + fooCounts.1.1 5 + + fooCounts.1.2 9 + fooCounts.2.1 5 + fooCounts.2.2 9 + fooCounts.3.1 5 + fooCounts.3.2 9 + fooCounts.4.1 5 + fooCounts.4.2 9 + fooCounts.5.1 5 + fooCounts.5.2 9 + fooCounts.6.1 5 + fooCounts.6.2 9 + fooCounts.7.2 9 -- note that row 1 doesn't exist for + fooCounts.8.2 9 -- times 7 and 8" + SYNTAX TimeTicks + +DataSource ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Identifies the source of the data that the associated + function is configured to analyze. This source can be any + interface on this device. + + In order to identify a particular interface, this + object shall identify the instance of the ifIndex + object, defined in [3,5], for the desired interface. + + For example, if an entry were to receive data from + interface #1, this object would be set to ifIndex.1." + SYNTAX OBJECT IDENTIFIER +-- +-- Protocol Directory Group +-- +-- Lists the inventory of protocols the probe has the capability of +-- monitoring and allows the addition, deletion, and configuration of +-- entries in this list. + +protocolDirLastChange OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time the protocol directory + was last modified, either through insertions or deletions, + or through modifications of either the + protocolDirAddressMapConfig, protocolDirHostConfig, or + protocolDirMatrixConfig." + ::= { protocolDir 1 } + +protocolDirTable OBJECT-TYPE + SYNTAX SEQUENCE OF ProtocolDirEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table lists the protocols that this agent has the + capability to decode and count. There is one entry in this + table for each such protocol. These protocols represent + different network layer, transport layer, and higher-layer + protocols. The agent should boot up with this table + preconfigured with those protocols that it knows about and + wishes to monitor. Implementations are strongly encouraged to + support protocols higher than the network layer (at least for + the protocol distribution group), even for implementations + that don't support the application layer groups." + ::= { protocolDir 2 } + +protocolDirEntry OBJECT-TYPE + SYNTAX ProtocolDirEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the protocolDirTable. + + An example of the indexing of this entry is + protocolDirLocalIndex.8.0.0.0.1.0.0.8.0.2.0.0, which is the + encoding of a length of 8, followed by 8 subids encoding the + protocolDirID of 1.2048, followed by a length of 2 and the + 2 subids encoding zero-valued parameters." + INDEX { protocolDirID, protocolDirParameters } + ::= { protocolDirTable 1 } + +ProtocolDirEntry ::= SEQUENCE { + protocolDirID OCTET STRING, + protocolDirParameters OCTET STRING, + protocolDirLocalIndex Integer32, + protocolDirDescr DisplayString, + protocolDirType BITS, + protocolDirAddressMapConfig INTEGER, + protocolDirHostConfig INTEGER, + protocolDirMatrixConfig INTEGER, + protocolDirOwner OwnerString, + protocolDirStatus RowStatus +} + +protocolDirID OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS not-accessible + + STATUS current + DESCRIPTION + "A unique identifier for a particular protocol. Standard + identifiers will be defined in a manner such that they + can often be used as specifications for new protocols - i.e. + a tree-structured assignment mechanism that matches the + protocol encapsulation `tree' and which has algorithmic + assignment mechanisms for certain subtrees. See RFC XXX for + more details. + + Despite the algorithmic mechanism, the probe will only place + entries in here for those protocols it chooses to collect. In + other words, it need not populate this table with all of the + possible ethernet protocol types, nor need it create them on + the fly when it sees them. Whether or not it does these + things is a matter of product definition (cost/benefit, + usability), and is up to the designer of the product. + + If an entry is written to this table with a protocolDirID that + the agent doesn't understand, either directly or + algorithmically, the SET request will be rejected with an + inconsistentName or badValue (for SNMPv1) error." + ::= { protocolDirEntry 1 } + +protocolDirParameters OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of parameters for the associated protocolDirID. + See the associated RMON2 Protocol Identifiers document + for a description of the possible parameters. There + will be one octet in this string for each sub-identifier in + the protocolDirID, and the parameters will appear here in the + same order as the associated sub-identifiers appear in the + protocolDirID. + + Every node in the protocolDirID tree has a different, optional + set of parameters defined (that is, the definition of + parameters for a node is optional). The proper parameter + value for each node is included in this string. Note that the + inclusion of a parameter value in this string for each node is + not optional - what is optional is that a node may have no + parameters defined, in which case the parameter field for that + node will be zero." + ::= { protocolDirEntry 2 } + +protocolDirLocalIndex OBJECT-TYPE + + + SYNTAX Integer32 (1..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The locally arbitrary, but unique identifier associated + with this protocolDir entry. + + The value for each supported protocol must remain constant at + least from one re-initialization of the entity's network + management system to the next re-initialization, except that + if a protocol is deleted and re-created, it must be re-created + with a new value that has not been used since the last + re-initialization. + + The specific value is meaningful only within a given SNMP + entity. A protocolDirLocalIndex must not be re-used until the + next agent-restart in the event the protocol directory entry + is deleted." + ::= { protocolDirEntry 3 } + +protocolDirDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (1..64)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A textual description of the protocol encapsulation. + A probe may choose to describe only a subset of the + entire encapsulation (e.g. only the highest layer). + + This object is intended for human consumption only. + + This object may not be modified if the associated + protocolDirStatus object is equal to active(1)." + ::= { protocolDirEntry 4 } + +protocolDirType OBJECT-TYPE + SYNTAX BITS { + extensible(0), + addressRecognitionCapable(1) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This object describes 2 attributes of this protocol + directory entry. + + The presence or absence of the `extensible' bit describes + whether or not this protocol directory entry can be extended + + + by the user by creating protocol directory entries which are + children of this protocol. + + An example of an entry that will often allow extensibility is + `ip.udp'. The probe may automatically populate some children + of this node such as `ip.udp.snmp' and `ip.udp.dns'. + A probe administrator or user may also populate additional + children via remote SNMP requests that create entries in this + table. When a child node is added for a protocol for which the + probe has no built in support, extending a parent node (for + which the probe does have built in support), + that child node is not extendible. This is termed `limited + extensibility'. + + When a child node is added through this extensibility + mechanism, the values of protocolDirLocalIndex and + protocolDirType shall be assigned by the agent. + + The other objects in the entry will be assigned by the + manager who is creating the new entry. + + This object also describes whether or not this agent can + recognize addresses for this protocol, should it be a network + level protocol. That is, while a probe may be able to + recognize packets of a particular network layer protocol and + count them, it takes additional logic to be able to recognize + the addresses in this protocol and to populate network layer + or application layer tables with the addresses in this + protocol. If this bit is set, the agent will recognize + network layer addresses for this protoocl and populate the + network and application layer host and matrix tables with + these protocols. + + Note that when an entry is created, the agent will supply + values for the bits that match the capabilities of the agent + with respect to this protocol. Note that since row creations + usually exercise the limited extensibility feature, these + bits will usually be set to zero." + ::= { protocolDirEntry 5 } + +protocolDirAddressMapConfig OBJECT-TYPE + SYNTAX INTEGER { + notSupported(1), + supportedOff(2), + supportedOn(3) + } + MAX-ACCESS read-create + STATUS current + + + DESCRIPTION + "This object describes and configures the probe's support for + address mapping for this protocol. When the probe creates + entries in this table for all protocols that it understands, + it will set the entry to notSupported(1) if it doesn't have + the capability to perform address mapping for the protocol or + if this protocol is not a network-layer protocol. When + an entry is created in this table by a management operation as + part of the limited extensibility feature, the probe must set + this value to notSupported(1), because limited extensibility + of the protocolDirTable does not extend to interpreting + addresses of the extended protocols. + + If the value of this object is notSupported(1), the probe + will not perform address mapping for this protocol and + shall not allow this object to be changed to any other value. + If the value of this object is supportedOn(3), the probe + supports address mapping for this protocol and is configured + to perform address mapping for this protocol for all + addressMappingControlEntries and all interfaces. + If the value of this object is supportedOff(2), the probe + supports address mapping for this protocol but is configured + to not perform address mapping for this protocol for any + addressMappingControlEntries and all interfaces. + Whenever this value changes from supportedOn(3) to + supportedOff(2), the probe shall delete all related entries in + the addressMappingTable." + ::= { protocolDirEntry 6 } + +protocolDirHostConfig OBJECT-TYPE + SYNTAX INTEGER { + notSupported(1), + supportedOff(2), + supportedOn(3) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object describes and configures the probe's support for + the network layer and application layer host tables for this + protocol. When the probe creates entries in this table for + all protocols that it understands, it will set the entry to + notSupported(1) if it doesn't have the capability to track the + nlHostTable for this protocol or if the alHostTable is + implemented but doesn't have the capability to track this + protocol. Note that if the alHostTable is implemented, the + probe may only support a protocol if it is supported in both + the nlHostTable and the alHostTable. + + + + If the associated protocolDirType object has the + addressRecognitionCapable bit set, then this is a network + layer protocol for which the probe recognizes addresses, and + thus the probe will populate the nlHostTable and alHostTable + with addresses it discovers for this protocol. + + If the value of this object is notSupported(1), the probe + will not track the nlHostTable or alHostTable for this + protocol and shall not allow this object to be changed to any + other value. If the value of this object is supportedOn(3), + the probe supports tracking of the nlHostTable and alHostTable + for this protocol and is configured to track both tables + for this protocol for all control entries and all interfaces. + If the value of this object is supportedOff(2), the probe + supports tracking of the nlHostTable and alHostTable for this + protocol but is configured to not track these tables + for any control entries or interfaces. + Whenever this value changes from supportedOn(3) to + supportedOff(2), the probe shall delete all related entries in + the nlHostTable and alHostTable. + + Note that since each alHostEntry references 2 protocol + directory entries, one for the network address and one for the + type of the highest protocol recognized, that an entry will + only be created in that table if this value is supportedOn(3) + for both protocols." + ::= { protocolDirEntry 7 } + +protocolDirMatrixConfig OBJECT-TYPE + SYNTAX INTEGER { + notSupported(1), + supportedOff(2), + supportedOn(3) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object describes and configures the probe's support for + the network layer and application layer matrix tables for this + protocol. When the probe creates entries in this table for + all protocols that it understands, it will set the entry to + notSupported(1) if it doesn't have the capability to track the + nlMatrixTables for this protocol or if the alMatrixTables are + implemented but don't have the capability to track this + protocol. Note that if the alMatrix tables are implemented, + the probe may only support a protocol if it is supported in + the the both of the nlMatrixTables and both of the + alMatrixTables. + + If the associated protocolDirType object has the + addressRecognitionCapable bit set, then this is a network + layer protocol for which the probe recognizes addresses, and + thus the probe will populate both of the nlMatrixTables and + both of the alMatrixTables with addresses it discovers for + this protocol. + + If the value of this object is notSupported(1), the probe + will not track either of the nlMatrixTables or the + alMatrixTables for this protocol and shall not allow this + object to be changed to any other value. If the value of this + object is supportedOn(3), the probe supports tracking of both + of the nlMatrixTables and (if implemented) both of the + alMatrixTables for this protocol and is configured to track + these tables for this protocol for all control entries and all + interfaces. If the value of this object is supportedOff(2), + the probe supports tracking of both of the nlMatrixTables and + (if implemented) both of the alMatrixTables for this protocol + but is configured to not track these tables for this + protocol for any control entries or interfaces. + Whenever this value changes from supportedOn(3) to + supportedOff(2), the probe shall delete all related entries in + the nlMatrixTables and the alMatrixTables. + + Note that since each alMatrixEntry references 2 protocol + directory entries, one for the network address and one for the + type of the highest protocol recognized, that an entry will + only be created in that table if this value is supportedOn(3) + for both protocols." + ::= { protocolDirEntry 8 } + +protocolDirOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { protocolDirEntry 9 } + +protocolDirStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this protocol directory entry. + + An entry may not exist in the active state unless all + + + objects in the entry have an appropriate value. + + If this object is not equal to active(1), all associated + entries in the nlHostTable, nlMatrixSDTable, nlMatrixDSTable, + alHostTable, alMatrixSDTable, and alMatrixDSTable shall be + deleted." + ::= { protocolDirEntry 10 } + +-- +-- Protocol Distribution Group (protocolDist) +-- +-- Collects the relative amounts of octets and packets for the +-- different protocols detected on a network segment. +-- protocolDistControlTable, +-- protocolDistStatsTable + +protocolDistControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF ProtocolDistControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Controls the setup of protocol type distribution statistics + tables. + + Implementations are encouraged to add an entry per monitored + interface upon initialization so that a default collection + of protocol statistics is available. + + Rationale: + This table controls collection of very basic statistics + for any or all of the protocols detected on a given interface. + An NMS can use this table to quickly determine bandwidth + allocation utilized by different protocols. + + A media-specific statistics collection could also + be configured (e.g. etherStats, trPStats) to easily obtain + total frame, octet, and droppedEvents for the same + interface." + ::= { protocolDist 1 } + +protocolDistControlEntry OBJECT-TYPE + SYNTAX ProtocolDistControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the protocolDistControlTable. + + An example of the indexing of this entry is + + + protocolDistControlDroppedFrames.7" + INDEX { protocolDistControlIndex } + ::= { protocolDistControlTable 1 } + +ProtocolDistControlEntry ::= SEQUENCE { + protocolDistControlIndex Integer32, + protocolDistControlDataSource DataSource, + protocolDistControlDroppedFrames Counter32, + protocolDistControlCreateTime LastCreateTime, + protocolDistControlOwner OwnerString, + protocolDistControlStatus RowStatus +} + +protocolDistControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A unique index for this protocolDistControlEntry." + ::= { protocolDistControlEntry 1 } + +protocolDistControlDataSource OBJECT-TYPE + SYNTAX DataSource + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The source of data for the this protocol distribution. + + The statistics in this group reflect all packets + on the local network segment attached to the + identified interface. + + This object may not be modified if the associated + protocolDistControlStatus object is equal to active(1)." + ::= { protocolDistControlEntry 2 } + +protocolDistControlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { protocolDistControlEntry 3 } + +protocolDistControlCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this control entry was last + activated. This can be used by the management station to + ensure that the table has not been deleted and recreated + between polls." + ::= { protocolDistControlEntry 4 } + +protocolDistControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { protocolDistControlEntry 5 } + +protocolDistControlStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this row. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value. + + If this object is not equal to active(1), all associated + entries in the protocolDistStatsTable shall be deleted." + ::= { protocolDistControlEntry 6 } + +-- per interface protocol distribution statistics table +protocolDistStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF ProtocolDistStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry is made in this table for every protocol in the + + + protocolDirTable which has been seen in at least one packet. + Counters are updated in this table for every protocol type + that is encountered when parsing a packet, but no counters are + updated for packets with MAC-layer errors. + + Note that if a protocolDirEntry is deleted, all associated + entries in this table are removed." + ::= { protocolDist 2 } + +protocolDistStatsEntry OBJECT-TYPE + SYNTAX ProtocolDistStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the protocolDistStatsTable. + + The index is composed of the protocolDistControlIndex of the + associated protocolDistControlEntry followed by the + protocolDirLocalIndex of the associated protocol that this + entry represents. In other words, the index identifies the + protocol distribution an entry is a part of as well as the + particular protocol that it represents. + + An example of the indexing of this entry is + protocolDistStatsPkts.1.18" + INDEX { protocolDistControlIndex, protocolDirLocalIndex } + ::= { protocolDistStatsTable 1 } + +ProtocolDistStatsEntry ::= SEQUENCE { + protocolDistStatsPkts ZeroBasedCounter32, + protocolDistStatsOctets ZeroBasedCounter32 +} + +protocolDistStatsPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets without errors received of this + protocol type. Note that this is the number of link-layer + packets, so if a single network-layer packet is fragmented + into several link-layer frames, this counter is incremented + several times." + ::= { protocolDistStatsEntry 1 } + +protocolDistStatsOctets OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets in packets received of this protocol + type since it was added to the protocolDistStatsTable + (excluding framing bits but including FCS octets), except for + those octets in packets that contained errors. + + Note this doesn't count just those octets in the particular + protocol frames, but includes the entire packet that contained + the protocol." + ::= { protocolDistStatsEntry 2 } + +-- +-- Address Map Group (addressMap) +-- +-- Lists MAC address to network address bindings discovered by the +-- probe and what interface they were last seen on. +-- addressMapControlTable +-- addressMapTable + +addressMapInserts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an address mapping entry has been + inserted into the addressMapTable. If an entry is inserted, + then deleted, and then inserted, this counter will be + incremented by 2. + + Note that the table size can be determined by subtracting + addressMapDeletes from addressMapInserts." + ::= { addressMap 1 } + +addressMapDeletes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an address mapping entry has been + deleted from the addressMapTable (for any reason). If + an entry is deleted, then inserted, and then deleted, this + counter will be incremented by 2. + + Note that the table size can be determined by subtracting + addressMapDeletes from addressMapInserts." + ::= { addressMap 2 } + + + + +addressMapMaxDesiredEntries OBJECT-TYPE + SYNTAX Integer32 (-1..2147483647) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The maximum number of entries that are desired in the + addressMapTable. The probe will not create more than + this number of entries in the table, but may choose to create + fewer entries in this table for any reason including the lack + of resources. + + If this object is set to a value less than the current number + of entries, enough entries are chosen in an + implementation-dependent manner and deleted so that the number + of entries in the table equals the value of this object. + + If this value is set to -1, the probe may create any number + of entries in this table. + + This object may be used to control how resources are allocated + on the probe for the various RMON functions." + ::= { addressMap 3 } + +addressMapControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF AddressMapControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table to control the collection of network layer address to + physical address to interface mappings. + + Note that this is not like the typical RMON + controlTable and dataTable in which each entry creates + its own data table. Each entry in this table enables the + discovery of addresses on a new interface and the placement + of address mappings into the central addressMapTable. + + Implementations are encouraged to add an entry per monitored + interface upon initialization so that a default collection + of address mappings is available." + ::= { addressMap 4 } + +addressMapControlEntry OBJECT-TYPE + SYNTAX AddressMapControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the addressMapControlTable. + + + An example of the indexing of this entry is + addressMapControlDroppedFrames.1" + INDEX { addressMapControlIndex } + ::= { addressMapControlTable 1 } + +AddressMapControlEntry ::= SEQUENCE { + addressMapControlIndex Integer32, + addressMapControlDataSource DataSource, + addressMapControlDroppedFrames Counter32, + addressMapControlOwner OwnerString, + addressMapControlStatus RowStatus +} + +addressMapControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A unique index for this entry in the addressMapControlTable." + ::= { addressMapControlEntry 1 } + +addressMapControlDataSource OBJECT-TYPE + SYNTAX DataSource + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The source of data for this addressMapControlEntry." + ::= { addressMapControlEntry 2 } + +addressMapControlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { addressMapControlEntry 3 } + + + + +addressMapControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { addressMapControlEntry 4 } + +addressMapControlStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this addressMap control entry. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value. + + If this object is not equal to active(1), all associated + entries in the addressMapTable shall be deleted." + ::= { addressMapControlEntry 5 } + +addressMapTable OBJECT-TYPE + SYNTAX SEQUENCE OF AddressMapEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table of network layer address to physical address to + interface mappings. + + The probe will add entries to this table based on the source + MAC and network addresses seen in packets without MAC-level + errors. The probe will populate this table for all protocols + in the protocol directory table whose value of + protocolDirAddressMapConfig is equal to supportedOn(3), and + will delete any entries whose protocolDirEntry is deleted or + has a protocolDirAddressMapConfig value of supportedOff(2)." + ::= { addressMap 5 } + +addressMapEntry OBJECT-TYPE + SYNTAX AddressMapEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the addressMapTable. + The protocolDirLocalIndex in the index identifies the network + layer protocol of the addressMapNetworkAddress. + + + An example of the indexing of this entry is + addressMapSource.783495.18.4.128.2.6.6.11.1.3.6.1.2.1.2.2.1.1.1" + INDEX { addressMapTimeMark, protocolDirLocalIndex, + addressMapNetworkAddress, addressMapSource } + ::= { addressMapTable 1 } + +AddressMapEntry ::= SEQUENCE { + addressMapTimeMark TimeFilter, + addressMapNetworkAddress OCTET STRING, + addressMapSource OBJECT IDENTIFIER, + addressMapPhysicalAddress OCTET STRING, + addressMapLastChange TimeStamp +} + +addressMapTimeMark OBJECT-TYPE + SYNTAX TimeFilter + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A TimeFilter for this entry. See the TimeFilter textual + convention to see how this works." + ::= { addressMapEntry 1 } + +addressMapNetworkAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The network address for this relation. + + This is represented as an octet string with + specific semantics and length as identified + by the protocolDirLocalIndex component of the + index. + + For example, if the protocolDirLocalIndex indicates an + encapsulation of ip, this object is encoded as a length + octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { addressMapEntry 2 } + +addressMapSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The interface or port on which the associated network + address was most recently seen. + + + + If this address mapping was discovered on an interface, this + object shall identify the instance of the ifIndex + object, defined in [3,5], for the desired interface. + For example, if an entry were to receive data from + interface #1, this object would be set to ifIndex.1. + + If this address mapping was discovered on a port, this + object shall identify the instance of the rptrGroupPortIndex + object, defined in [RFC1516], for the desired port. + For example, if an entry were to receive data from + group #1, port #1, this object would be set to + rptrGroupPortIndex.1.1. + + Note that while the dataSource associated with this entry + may only point to index objects, this object may at times + point to repeater port objects. This situation occurs when + the dataSource points to an interface which is a locally + attached repeater and the agent has additional information + about the source port of traffic seen on that repeater." + ::= { addressMapEntry 3 } + +addressMapPhysicalAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The last source physical address on which the associated + network address was seen. If the protocol of the associated + network address was encapsulated inside of a network-level or + higher protocol, this will be the address of the next-lower + protocol with the addressRecognitionCapable bit enabled and + will be formatted as specified for that protocol." + ::= { addressMapEntry 4 } + +addressMapLastChange OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time this entry was last + created or the values of the physical address changed. + + This can be used to help detect duplicate address problems, in + which case this object will be updated frequently." + ::= { addressMapEntry 5 } + +-- +-- Network Layer Host Group + + + +-- +-- Counts the amount of traffic sent from and to each network address +-- discovered by the probe. +-- Note that while the hlHostControlTable also has objects that +-- control an optional alHostTable, implementation of the alHostTable is +-- not required to fully implement this group. + +hlHostControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HlHostControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of higher layer (i.e. non-MAC) host table control entries. + + These entries will enable the collection of the network and + application level host tables indexed by network addresses. + Both the network and application level host tables are + controlled by this table is so that they will both be created + and deleted at the same time, further increasing the ease with + which they can be implemented as a single datastore (note that + if an implementation stores application layer host records in + memory, it can derive network layer host records from them). + + Entries in the nlHostTable will be created on behalf of each + entry in this table. Additionally, if this probe implements + the alHostTable, entries in the alHostTable will be created on + behalf of each entry in this table. + + Implementations are encouraged to add an entry per monitored + interface upon initialization so that a default collection + of host statistics is available." + ::= { nlHost 1 } + +hlHostControlEntry OBJECT-TYPE + SYNTAX HlHostControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the hlHostControlTable. + + An example of the indexing of this entry is + hlHostControlNlDroppedFrames.1" + INDEX { hlHostControlIndex } + ::= { hlHostControlTable 1 } + +HlHostControlEntry ::= SEQUENCE { + hlHostControlIndex Integer32, + hlHostControlDataSource DataSource, + + + hlHostControlNlDroppedFrames Counter32, + hlHostControlNlInserts Counter32, + hlHostControlNlDeletes Counter32, + hlHostControlNlMaxDesiredEntries Integer32, + hlHostControlAlDroppedFrames Counter32, + hlHostControlAlInserts Counter32, + hlHostControlAlDeletes Counter32, + hlHostControlAlMaxDesiredEntries Integer32, + hlHostControlOwner OwnerString, + hlHostControlStatus RowStatus +} + +hlHostControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in the + hlHostControlTable. Each such entry defines + a function that discovers hosts on a particular + interface and places statistics about them in the + nlHostTable, and optionally in the alHostTable, on + behalf of this hlHostControlEntry." + ::= { hlHostControlEntry 1 } + +hlHostControlDataSource OBJECT-TYPE + SYNTAX DataSource + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The source of data for the associated host tables. + + The statistics in this group reflect all packets + on the local network segment attached to the + identified interface. + + This object may not be modified if the associated + hlHostControlStatus object is equal to active(1)." + ::= { hlHostControlEntry 2 } + +hlHostControlNlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for the associated + + nlHost entries for whatever reason. Most often, this event + occurs when the probe is out of some resources and decides to + shed load from this collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that if the nlHostTable is inactive because no protocols + are enabled in the protocol directory, this value should be 0. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { hlHostControlEntry 3 } + +hlHostControlNlInserts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an nlHost entry has been + inserted into the nlHost table. If an entry is inserted, then + deleted, and then inserted, this counter will be incremented + by 2. + + To allow for efficient implementation strategies, agents may + delay updating this object for short periods of time. For + example, an implementation strategy may allow internal + data structures to differ from those visible via SNMP for + short periods of time. This counter may reflect the internal + data structures for those short periods of time. + + Note that the table size can be determined by subtracting + hlHostControlNlDeletes from hlHostControlNlInserts." + ::= { hlHostControlEntry 4 } + +hlHostControlNlDeletes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an nlHost entry has been + deleted from the nlHost table (for any reason). If an entry + is deleted, then inserted, and then deleted, this counter will + be incremented by 2. + + To allow for efficient implementation strategies, agents may + delay updating this object for short periods of time. For + example, an implementation strategy may allow internal + + + data structures to differ from those visible via SNMP for + short periods of time. This counter may reflect the internal + data structures for those short periods of time. + + Note that the table size can be determined by subtracting + hlHostControlNlDeletes from hlHostControlNlInserts." + ::= { hlHostControlEntry 5 } + +hlHostControlNlMaxDesiredEntries OBJECT-TYPE + SYNTAX Integer32 (-1..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum number of entries that are desired in the + nlHostTable on behalf of this control entry. The probe will + not create more than this number of associated entries in the + table, but may choose to create fewer entries in this table + for any reason including the lack of resources. + + If this object is set to a value less than the current number + of entries, enough entries are chosen in an + implementation-dependent manner and deleted so that the number + of entries in the table equals the value of this object. + + If this value is set to -1, the probe may create any number + of entries in this table. If the associated + hlHostControlStatus object is equal to `active', this + object may not be modified. + + This object may be used to control how resources are allocated + on the probe for the various RMON functions." + ::= { hlHostControlEntry 6 } + +hlHostControlAlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for the associated + alHost entries for whatever reason. Most often, this event + occurs when the probe is out of some resources and decides to + shed load from this collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that if the alHostTable is not implemented or is inactive + because no protocols are enabled in the protocol directory, + this value should be 0. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { hlHostControlEntry 7 } + +hlHostControlAlInserts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an alHost entry has been + inserted into the alHost table. If an entry is inserted, then + deleted, and then inserted, this counter will be incremented + by 2. + + To allow for efficient implementation strategies, agents may + delay updating this object for short periods of time. For + example, an implementation strategy may allow internal + data structures to differ from those visible via SNMP for + short periods of time. This counter may reflect the internal + data structures for those short periods of time. + + Note that the table size can be determined by subtracting + hlHostControlAlDeletes from hlHostControlAlInserts." + ::= { hlHostControlEntry 8 } + +hlHostControlAlDeletes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an alHost entry has been + deleted from the alHost table (for any reason). If an entry + is deleted, then inserted, and then deleted, this counter will + be incremented by 2. + + To allow for efficient implementation strategies, agents may + delay updating this object for short periods of time. For + example, an implementation strategy may allow internal + data structures to differ from those visible via SNMP for + short periods of time. This counter may reflect the internal + data structures for those short periods of time. + + Note that the table size can be determined by subtracting + hlHostControlAlDeletes from hlHostControlAlInserts." + + + + ::= { hlHostControlEntry 9 } + +hlHostControlAlMaxDesiredEntries OBJECT-TYPE + SYNTAX Integer32 (-1..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum number of entries that are desired in the alHost + table on behalf of this control entry. The probe will not + create more than this number of associated entries in the + table, but may choose to create fewer entries in this table + for any reason including the lack of resources. + + If this object is set to a value less than the current number + of entries, enough entries are chosen in an + implementation-dependent manner and deleted so that the number + of entries in the table equals the value of this object. + + If this value is set to -1, the probe may create any number + of entries in this table. If the associated + hlHostControlStatus object is equal to `active', this + object may not be modified. + + This object may be used to control how resources are allocated + on the probe for the various RMON functions." + ::= { hlHostControlEntry 10 } + +hlHostControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { hlHostControlEntry 11 } + +hlHostControlStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this hlHostControlEntry. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value. + + If this object is not equal to active(1), all associated + entries in the nlHostTable and alHostTable shall be deleted." + ::= { hlHostControlEntry 12 } + +nlHostTable OBJECT-TYPE + SYNTAX SEQUENCE OF NlHostEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A collection of statistics for a particular network layer + address that has been discovered on an interface of this + device. + + The probe will populate this table for all network layer + protocols in the protocol directory table whose value of + protocolDirHostConfig is equal to supportedOn(3), and + will delete any entries whose protocolDirEntry is deleted or + has a protocolDirHostConfig value of supportedOff(2). + + The probe will add to this table all addresses seen + as the source or destination address in all packets with no + MAC errors, and will increment octet and packet counts in the + table for all packets with no MAC errors." +::= { nlHost 2 } + +nlHostEntry OBJECT-TYPE + SYNTAX NlHostEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the nlHostTable. + + The hlHostControlIndex value in the index identifies the + hlHostControlEntry on whose behalf this entry was created. + The protocolDirLocalIndex value in the index identifies the + network layer protocol of the nlHostAddress. + + An example of the indexing of this entry is + nlHostOutPkts.1.783495.18.4.128.2.6.6." + INDEX { hlHostControlIndex, nlHostTimeMark, + protocolDirLocalIndex, nlHostAddress } + ::= { nlHostTable 1 } + +NlHostEntry ::= SEQUENCE { + nlHostTimeMark TimeFilter, + nlHostAddress OCTET STRING, + nlHostInPkts ZeroBasedCounter32, + nlHostOutPkts ZeroBasedCounter32, + nlHostInOctets ZeroBasedCounter32, + nlHostOutOctets ZeroBasedCounter32, + + + nlHostOutMacNonUnicastPkts ZeroBasedCounter32, + nlHostCreateTime LastCreateTime +} + +nlHostTimeMark OBJECT-TYPE + SYNTAX TimeFilter + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A TimeFilter for this entry. See the TimeFilter textual + convention to see how this works." + ::= { nlHostEntry 1 } + +nlHostAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The network address for this nlHostEntry. + + This is represented as an octet string with + specific semantics and length as identified + by the protocolDirLocalIndex component of the index. + + For example, if the protocolDirLocalIndex indicates an + encapsulation of ip, this object is encoded as a length + octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { nlHostEntry 2 } + +nlHostInPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets without errors transmitted to + this address since it was added to the nlHostTable. Note that + this is the number of link-layer packets, so if a single + network-layer packet is fragmented into several link-layer + frames, this counter is incremented several times." + ::= { nlHostEntry 3 } + +nlHostOutPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets without errors transmitted by + + + this address since it was added to the nlHostTable. Note that + this is the number of link-layer packets, so if a single + network-layer packet is fragmented into several link-layer + frames, this counter is incremented several times." + ::= { nlHostEntry 4 } + +nlHostInOctets OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted to this address + since it was added to the nlHostTable (excluding + framing bits but including FCS octets), excluding + those octets in packets that contained errors. + + Note this doesn't count just those octets in the particular + protocol frames, but includes the entire packet that contained + the protocol." + ::= { nlHostEntry 5 } + +nlHostOutOctets OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted by this address + since it was added to the nlHostTable (excluding + framing bits but including FCS octets), excluding + those octets in packets that contained errors. + + Note this doesn't count just those octets in the particular + protocol frames, but includes the entire packet that contained + the protocol." + ::= { nlHostEntry 6 } + +nlHostOutMacNonUnicastPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets without errors transmitted by this + address that were directed to any MAC broadcast addresses + or to any MAC multicast addresses since this host was + added to the nlHostTable. Note that this is the number of + link-layer packets, so if a single network-layer packet is + fragmented into several link-layer frames, this counter is + incremented several times." + + + + ::= { nlHostEntry 7 } + +nlHostCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this entry was last activated. + This can be used by the management station to ensure that the + entry has not been deleted and recreated between polls." + ::= { nlHostEntry 8 } + +-- +-- Network Layer Matrix Group +-- +-- Counts the amount of traffic sent between each pair of network +-- addresses discovered by the probe. +-- Note that while the hlMatrixControlTable also has objects that +-- control optional alMatrixTables, implementation of the +-- alMatrixTables is not required to fully implement this group. + +hlMatrixControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HlMatrixControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of higher layer (i.e. non-MAC) matrix control entries. + + These entries will enable the collection of the network and + application level matrix tables containing conversation + statistics indexed by pairs of network addresses. + Both the network and application level matrix tables are + controlled by this table is so that they will both be created + and deleted at the same time, further increasing the ease with + which they can be implemented as a single datastore (note that + if an implementation stores application layer matrix records + in memory, it can derive network layer matrix records from + them). + + Entries in the nlMatrixSDTable and nlMatrixDSTable will be + created on behalf of each entry in this table. Additionally, + if this probe implements the alMatrix tables, entries in the + alMatrix tables will be created on behalf of each entry in + this table." + ::= { nlMatrix 1 } + +hlMatrixControlEntry OBJECT-TYPE + SYNTAX HlMatrixControlEntry + + + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the hlMatrixControlTable. + + An example of indexing of this entry is + hlMatrixControlNlDroppedFrames.1" + INDEX { hlMatrixControlIndex } + ::= { hlMatrixControlTable 1 } + +HlMatrixControlEntry ::= SEQUENCE { + hlMatrixControlIndex Integer32, + hlMatrixControlDataSource DataSource, + hlMatrixControlNlDroppedFrames Counter32, + hlMatrixControlNlInserts Counter32, + hlMatrixControlNlDeletes Counter32, + hlMatrixControlNlMaxDesiredEntries Integer32, + hlMatrixControlAlDroppedFrames Counter32, + hlMatrixControlAlInserts Counter32, + hlMatrixControlAlDeletes Counter32, + hlMatrixControlAlMaxDesiredEntries Integer32, + hlMatrixControlOwner OwnerString, + hlMatrixControlStatus RowStatus +} + +hlMatrixControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in the + hlMatrixControlTable. Each such entry defines + a function that discovers conversations on a particular + interface and places statistics about them in the + nlMatrixSDTable and the nlMatrixDSTable, and optionally the + alMatrixSDTable and alMatrixDSTable, on behalf of this + hlMatrixControlEntry." + ::= { hlMatrixControlEntry 1 } + +hlMatrixControlDataSource OBJECT-TYPE + SYNTAX DataSource + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The source of the data for the associated matrix tables. + + The statistics in this group reflect all packets + on the local network segment attached to the + + + identified interface. + + This object may not be modified if the associated + hlMatrixControlStatus object is equal to active(1)." + ::= { hlMatrixControlEntry 2 } + +hlMatrixControlNlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that if the nlMatrixTables are inactive because no + protocols are enabled in the protocol directory, this value + should be 0. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { hlMatrixControlEntry 3 } + +hlMatrixControlNlInserts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an nlMatrix entry has been + inserted into the nlMatrix tables. If an entry is inserted, + then deleted, and then inserted, this counter will be + incremented by 2. The addition of a conversation into both + the nlMatrixSDTable and nlMatrixDSTable shall be counted as + two insertions (even though every addition into one table must + be accompanied by an insertion into the other). + + To allow for efficient implementation strategies, agents may + delay updating this object for short periods of time. For + example, an implementation strategy may allow internal + data structures to differ from those visible via SNMP for + short periods of time. This counter may reflect the internal + data structures for those short periods of time. + + + Note that the sum of then nlMatrixSDTable and nlMatrixDSTable + sizes can be determined by subtracting + hlMatrixControlNlDeletes from hlMatrixControlNlInserts." + ::= { hlMatrixControlEntry 4 } + +hlMatrixControlNlDeletes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an nlMatrix entry has been + deleted from the nlMatrix tables (for any reason). If an + entry is deleted, then inserted, and then deleted, this + counter will be incremented by 2. The deletion of a + conversation from both the nlMatrixSDTable and nlMatrixDSTable + shall be counted as two deletions (even though every deletion + from one table must be accompanied by a deletion from the + other). + + To allow for efficient implementation strategies, agents may + delay updating this object for short periods of time. For + example, an implementation strategy may allow internal + data structures to differ from those visible via SNMP for + short periods of time. This counter may reflect the internal + data structures for those short periods of time. + + Note that the table size can be determined by subtracting + hlMatrixControlNlDeletes from hlMatrixControlNlInserts." + ::= { hlMatrixControlEntry 5 } + +hlMatrixControlNlMaxDesiredEntries OBJECT-TYPE + SYNTAX Integer32 (-1..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum number of entries that are desired in the + nlMatrix tables on behalf of this control entry. The probe + will not create more than this number of associated entries in + the table, but may choose to create fewer entries in this + table for any reason including the lack of resources. + + If this object is set to a value less than the current number + of entries, enough entries are chosen in an + implementation-dependent manner and deleted so that the number + of entries in the table equals the value of this object. + + If this value is set to -1, the probe may create any number + of entries in this table. If the associated + + + + + hlMatrixControlStatus object is equal to `active', this + object may not be modified. + + This object may be used to control how resources are allocated + on the probe for the various RMON functions." + ::= { hlMatrixControlEntry 6 } + +hlMatrixControlAlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that if the alMatrixTables are not implemented or are + inactive because no protocols are enabled in the protocol + directory, this value should be 0. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { hlMatrixControlEntry 7 } + +hlMatrixControlAlInserts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an alMatrix entry has been + inserted into the alMatrix tables. If an entry is inserted, + then deleted, and then inserted, this counter will be + incremented by 2. The addition of a conversation into both + the alMatrixSDTable and alMatrixDSTable shall be counted as + two insertions (even though every addition into one table must + be accompanied by an insertion into the other). + + To allow for efficient implementation strategies, agents may + delay updating this object for short periods of time. For + example, an implementation strategy may allow internal + data structures to differ from those visible via SNMP for + short periods of time. This counter may reflect the internal + + data structures for those short periods of time. + + Note that the table size can be determined by subtracting + hlMatrixControlAlDeletes from hlMatrixControlAlInserts." + ::= { hlMatrixControlEntry 8 } + +hlMatrixControlAlDeletes OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times an alMatrix entry has been + deleted from the alMatrix tables. If an entry is deleted, + then inserted, and then deleted, this counter will be + incremented by 2. The deletion of a conversation from both + the alMatrixSDTable and alMatrixDSTable shall be counted as + two deletions (even though every deletion from one table must + be accompanied by a deletion from the other). + + To allow for efficient implementation strategies, agents may + delay updating this object for short periods of time. For + example, an implementation strategy may allow internal + data structures to differ from those visible via SNMP for + short periods of time. This counter may reflect the internal + data structures for those short periods of time. + + Note that the table size can be determined by subtracting + hlMatrixControlAlDeletes from hlMatrixControlAlInserts." + ::= { hlMatrixControlEntry 9 } + +hlMatrixControlAlMaxDesiredEntries OBJECT-TYPE + SYNTAX Integer32 (-1..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum number of entries that are desired in the + alMatrix tables on behalf of this control entry. The probe + will not create more than this number of associated entries in + the table, but may choose to create fewer entries in this + table for any reason including the lack of resources. + + If this object is set to a value less than the current number + of entries, enough entries are chosen in an + implementation-dependent manner and deleted so that the number + of entries in the table equals the value of this object. + + If this value is set to -1, the probe may create any number + of entries in this table. If the associated + + + hlMatrixControlStatus object is equal to `active', this + object may not be modified. + + This object may be used to control how resources are allocated + on the probe for the various RMON functions." + ::= { hlMatrixControlEntry 10 } + +hlMatrixControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { hlMatrixControlEntry 11 } + +hlMatrixControlStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this hlMatrixControlEntry. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value. + + If this object is not equal to active(1), all + associated entries in the nlMatrixSDTable, + nlMatrixDSTable, alMatrixSDTable, and the alMatrixDSTable + shall be deleted by the agent." + ::= { hlMatrixControlEntry 12 } + +nlMatrixSDTable OBJECT-TYPE + SYNTAX SEQUENCE OF NlMatrixSDEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of traffic matrix entries which collect statistics for + conversations between two network-level addresses. This table + is indexed first by the source address and then by the + destination address to make it convenient to collect all + conversations from a particular address. + + The probe will populate this table for all network layer + protocols in the protocol directory table whose value of + protocolDirMatrixConfig is equal to supportedOn(3), and + will delete any entries whose protocolDirEntry is deleted or + has a protocolDirMatrixConfig value of supportedOff(2). + + The probe will add to this table all pairs of addresses + seen in all packets with no MAC errors, and will increment + octet and packet counts in the table for all packets with no + MAC errors. + + Further, this table will only contain entries that have a + corresponding entry in the nlMatrixDSTable with the same + source address and destination address." + ::= { nlMatrix 2 } + +nlMatrixSDEntry OBJECT-TYPE + SYNTAX NlMatrixSDEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the nlMatrixSDTable. + + The hlMatrixControlIndex value in the index identifies the + hlMatrixControlEntry on whose behalf this entry was created. + The protocolDirLocalIndex value in the index identifies the + network layer protocol of the nlMatrixSDSourceAddress and + nlMatrixSDDestAddress. + + An example of the indexing of this table is + nlMatrixSDPkts.1.783495.18.4.128.2.6.6.4.128.2.6.7" + INDEX { hlMatrixControlIndex, nlMatrixSDTimeMark, + protocolDirLocalIndex, + nlMatrixSDSourceAddress, nlMatrixSDDestAddress } + ::= { nlMatrixSDTable 1 } + +NlMatrixSDEntry ::= SEQUENCE { + nlMatrixSDTimeMark TimeFilter, + nlMatrixSDSourceAddress OCTET STRING, + nlMatrixSDDestAddress OCTET STRING, + nlMatrixSDPkts ZeroBasedCounter32, + nlMatrixSDOctets ZeroBasedCounter32, + nlMatrixSDCreateTime LastCreateTime +} + +nlMatrixSDTimeMark OBJECT-TYPE + SYNTAX TimeFilter + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A TimeFilter for this entry. See the TimeFilter textual + convention to see how this works." + ::= { nlMatrixSDEntry 1 } + + + +nlMatrixSDSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The network source address for this nlMatrixSDEntry. + + This is represented as an octet string with + specific semantics and length as identified + by the protocolDirLocalIndex component of the index. + + For example, if the protocolDirLocalIndex indicates an + encapsulation of ip, this object is encoded as a length + octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { nlMatrixSDEntry 2 } + +nlMatrixSDDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The network destination address for this + nlMatrixSDEntry. + + This is represented as an octet string with + specific semantics and length as identified + by the protocolDirLocalIndex component of the index. + + For example, if the protocolDirLocalIndex indicates an + encapsulation of ip, this object is encoded as a length + octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { nlMatrixSDEntry 3 } + +nlMatrixSDPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets without errors transmitted from the + source address to the destination address since this entry was + added to the nlMatrixSDTable. Note that this is the number of + link-layer packets, so if a single network-layer packet is + fragmented into several link-layer frames, this counter is + incremented several times." + ::= { nlMatrixSDEntry 4 } + + + +nlMatrixSDOctets OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted from the source address to + the destination address since this entry was added to the + nlMatrixSDTable (excluding framing bits but + including FCS octets), excluding those octets in packets that + contained errors. + + Note this doesn't count just those octets in the particular + protocol frames, but includes the entire packet that contained + the protocol." + ::= { nlMatrixSDEntry 5 } + +nlMatrixSDCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this entry was last activated. + This can be used by the management station to ensure that the + entry has not been deleted and recreated between polls." + ::= { nlMatrixSDEntry 6 } + + +-- Traffic matrix tables from destination to source + +nlMatrixDSTable OBJECT-TYPE + SYNTAX SEQUENCE OF NlMatrixDSEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of traffic matrix entries which collect statistics for + conversations between two network-level addresses. This table + is indexed first by the destination address and then by the + source address to make it convenient to collect all + conversations to a particular address. + + The probe will populate this table for all network layer + protocols in the protocol directory table whose value of + protocolDirMatrixConfig is equal to supportedOn(3), and + will delete any entries whose protocolDirEntry is deleted or + has a protocolDirMatrixConfig value of supportedOff(2). + + The probe will add to this table all pairs of addresses + seen in all packets with no MAC errors, and will increment + + + octet and packet counts in the table for all packets with no + MAC errors. + + Further, this table will only contain entries that have a + corresponding entry in the nlMatrixSDTable with the same + source address and destination address." + ::= { nlMatrix 3 } + +nlMatrixDSEntry OBJECT-TYPE + SYNTAX NlMatrixDSEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the nlMatrixDSTable. + + The hlMatrixControlIndex value in the index identifies the + hlMatrixControlEntry on whose behalf this entry was created. + The protocolDirLocalIndex value in the index identifies the + network layer protocol of the nlMatrixDSSourceAddress and + nlMatrixDSDestAddress. + + An example of the indexing of this table is + nlMatrixDSPkts.1.783495.18.4.128.2.6.7.4.128.2.6.6" + INDEX { hlMatrixControlIndex, nlMatrixDSTimeMark, + protocolDirLocalIndex, + nlMatrixDSDestAddress, nlMatrixDSSourceAddress } + ::= { nlMatrixDSTable 1 } + +NlMatrixDSEntry ::= SEQUENCE { + nlMatrixDSTimeMark TimeFilter, + nlMatrixDSSourceAddress OCTET STRING, + nlMatrixDSDestAddress OCTET STRING, + nlMatrixDSPkts ZeroBasedCounter32, + nlMatrixDSOctets ZeroBasedCounter32, + nlMatrixDSCreateTime LastCreateTime +} + +nlMatrixDSTimeMark OBJECT-TYPE + SYNTAX TimeFilter + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A TimeFilter for this entry. See the TimeFilter textual + convention to see how this works." + ::= { nlMatrixDSEntry 1 } + +nlMatrixDSSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + + + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The network source address for this nlMatrixDSEntry. + + This is represented as an octet string with + specific semantics and length as identified + by the protocolDirLocalIndex component of the index. + + For example, if the protocolDirLocalIndex indicates an + encapsulation of ip, this object is encoded as a length + octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { nlMatrixDSEntry 2 } + +nlMatrixDSDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The network destination address for this + nlMatrixDSEntry. + + This is represented as an octet string with + specific semantics and length as identified + by the protocolDirLocalIndex component of the index. + + For example, if the protocolDirLocalIndex indicates an + encapsulation of ip, this object is encoded as a length + octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { nlMatrixDSEntry 3 } + +nlMatrixDSPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets without errors transmitted from the + source address to the destination address since this entry was + added to the nlMatrixDSTable. Note that this is the number of + link-layer packets, so if a single network-layer packet is + fragmented into several link-layer frames, this counter is + incremented several times." + ::= { nlMatrixDSEntry 4 } + +nlMatrixDSOctets OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted from the source address + to the destination address since this entry was added to the + nlMatrixDSTable (excluding framing bits but + including FCS octets), excluding those octets in packets that + contained errors. + + Note this doesn't count just those octets in the particular + protocol frames, but includes the entire packet that contained + the protocol." + ::= { nlMatrixDSEntry 5 } + +nlMatrixDSCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this entry was last activated. + This can be used by the management station to ensure that the + entry has not been deleted and recreated between polls." + ::= { nlMatrixDSEntry 6 } + +nlMatrixTopNControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF NlMatrixTopNControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of parameters that control the creation of a + report of the top N matrix entries according to + a selected metric." + ::= { nlMatrix 4 } + +nlMatrixTopNControlEntry OBJECT-TYPE + SYNTAX NlMatrixTopNControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the nlMatrixTopNControlTable. + + An example of the indexing of this table is + nlMatrixTopNControlDuration.3" + INDEX { nlMatrixTopNControlIndex } + ::= { nlMatrixTopNControlTable 1 } + +NlMatrixTopNControlEntry ::= SEQUENCE { + nlMatrixTopNControlIndex Integer32, + + + nlMatrixTopNControlMatrixIndex Integer32, + nlMatrixTopNControlRateBase INTEGER, + nlMatrixTopNControlTimeRemaining Integer32, + nlMatrixTopNControlGeneratedReports Counter32, + nlMatrixTopNControlDuration Integer32, + nlMatrixTopNControlRequestedSize Integer32, + nlMatrixTopNControlGrantedSize Integer32, + nlMatrixTopNControlStartTime TimeStamp, + nlMatrixTopNControlOwner OwnerString, + nlMatrixTopNControlStatus RowStatus +} + +nlMatrixTopNControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry + in the nlMatrixTopNControlTable. Each such + entry defines one top N report prepared for + one interface." + ::= { nlMatrixTopNControlEntry 1 } + +nlMatrixTopNControlMatrixIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The nlMatrix[SD/DS] table for which a top N report will be + prepared on behalf of this entry. The nlMatrix[SD/DS] table + is identified by the value of the hlMatrixControlIndex + for that table - that value is used here to identify the + particular table. + + This object may not be modified if the associated + nlMatrixTopNControlStatus object is equal to active(1)." + ::= { nlMatrixTopNControlEntry 2 } + +nlMatrixTopNControlRateBase OBJECT-TYPE + SYNTAX INTEGER { + nlMatrixTopNPkts(1), + nlMatrixTopNOctets(2) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The variable for each nlMatrix[SD/DS] entry that the + nlMatrixTopNEntries are sorted by. + + + This object may not be modified if the associated + nlMatrixTopNControlStatus object is equal to active(1)." + ::= { nlMatrixTopNControlEntry 3 } + +nlMatrixTopNControlTimeRemaining OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The number of seconds left in the report currently + being collected. When this object is modified by + the management station, a new collection is started, + possibly aborting a currently running report. The + new value is used as the requested duration of this + report, and is immediately loaded into the associated + nlMatrixTopNControlDuration object. + When the report finishes, the probe will automatically + start another collection with the same initial value + of nlMatrixTopNControlTimeRemaining. Thus the management + station may simply read the resulting reports repeatedly, + checking the startTime and duration each time to ensure that a + report was not missed or that the report parameters were not + changed. + + While the value of this object is non-zero, it decrements + by one per second until it reaches zero. At the time + that this object decrements to zero, the report is made + accessible in the nlMatrixTopNTable, overwriting any report + that may be there. + + When this object is modified by the management station, any + associated entries in the nlMatrixTopNTable shall be deleted. + + (Note that this is a different algorithm than the one used in + the hostTopNTable)." + DEFVAL { 1800 } + ::= { nlMatrixTopNControlEntry 4 } + +nlMatrixTopNControlGeneratedReports OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of reports that have been generated by this entry." + ::= { nlMatrixTopNControlEntry 5 } + +nlMatrixTopNControlDuration OBJECT-TYPE + SYNTAX Integer32 + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of seconds that this report has collected + during the last sampling interval. + + When the associated nlMatrixTopNControlTimeRemaining object is + set, this object shall be set by the probe to the + same value and shall not be modified until the next + time the nlMatrixTopNControlTimeRemaining is set. + This value shall be zero if no reports have been + requested for this nlMatrixTopNControlEntry." + ::= { nlMatrixTopNControlEntry 6 } + +nlMatrixTopNControlRequestedSize OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum number of matrix entries requested for this report. + + When this object is created or modified, the probe + should set nlMatrixTopNControlGrantedSize as closely to this + object as is possible for the particular probe + implementation and available resources." + DEFVAL { 150 } + ::= { nlMatrixTopNControlEntry 7 } + +nlMatrixTopNControlGrantedSize OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum number of matrix entries in this report. + + When the associated nlMatrixTopNControlRequestedSize object is + created or modified, the probe should set this + object as closely to the requested value as is + possible for the particular implementation and + available resources. The probe must not lower this + value except as a result of a set to the associated + nlMatrixTopNControlRequestedSize object. + + If the value of nlMatrixTopNControlRateBase is equal to + nlMatrixTopNPkts, when the next topN report is generated, + matrix entries with the highest value of nlMatrixTopNPktRate + shall be placed in this table in decreasing order of this rate + until there is no more room or until there are no more + + + matrix entries. + + If the value of nlMatrixTopNControlRateBase is equal to + nlMatrixTopNOctets, when the next topN report is generated, + matrix entries with the highest value of nlMatrixTopNOctetRate + shall be placed in this table in decreasing order of this rate + until there is no more room or until there are no more + matrix entries. + + It is an implementation-specific matter how entries with the + same value of nlMatrixTopNPktRate or nlMatrixTopNOctetRate are + sorted. It is also an implementation-specific matter as to + whether or not zero-valued entries are available." + ::= { nlMatrixTopNControlEntry 8 } + +nlMatrixTopNControlStartTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this top N report was + last started. In other words, this is the time that + the associated nlMatrixTopNControlTimeRemaining object was + modified to start the requested report or the time + the report was last automatically (re)started. + + This object may be used by the management station to + determine if a report was missed or not." + ::= { nlMatrixTopNControlEntry 9 } + +nlMatrixTopNControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { nlMatrixTopNControlEntry 10 } + +nlMatrixTopNControlStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this nlMatrixTopNControlEntry. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value. + + + If this object is not equal to active(1), all + associated entries in the nlMatrixTopNTable shall be deleted + by the agent." + ::= { nlMatrixTopNControlEntry 11 } + +nlMatrixTopNTable OBJECT-TYPE + SYNTAX SEQUENCE OF NlMatrixTopNEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of statistics for those network layer matrix entries + that have counted the highest number of octets or packets." + ::= { nlMatrix 5 } + +nlMatrixTopNEntry OBJECT-TYPE + SYNTAX NlMatrixTopNEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the nlMatrixTopNTable. + + The nlMatrixTopNControlIndex value in the index identifies the + nlMatrixTopNControlEntry on whose behalf this entry was + created. + + An example of the indexing of this table is + nlMatrixTopNPktRate.3.10" + INDEX { nlMatrixTopNControlIndex, nlMatrixTopNIndex } + ::= { nlMatrixTopNTable 1 } + +NlMatrixTopNEntry ::= SEQUENCE { + nlMatrixTopNIndex Integer32, + nlMatrixTopNProtocolDirLocalIndex Integer32, + nlMatrixTopNSourceAddress OCTET STRING, + nlMatrixTopNDestAddress OCTET STRING, + nlMatrixTopNPktRate Gauge32, + nlMatrixTopNReversePktRate Gauge32, + nlMatrixTopNOctetRate Gauge32, + nlMatrixTopNReverseOctetRate Gauge32 +} + +nlMatrixTopNIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in + the nlMatrixTopNTable among those in the same report. + + + This index is between 1 and N, where N is the + number of entries in this report. + + If the value of nlMatrixTopNControlRateBase is equal to + nlMatrixTopNPkts, increasing values of nlMatrixTopNIndex shall + be assigned to entries with decreasing values of + nlMatrixTopNPktRate until index N is assigned or there are no + more nlMatrixTopNEntries. + + If the value of nlMatrixTopNControlRateBase is equal to + nlMatrixTopNOctets, increasing values of nlMatrixTopNIndex + shall be assigned to entries with decreasing values of + nlMatrixTopNOctetRate until index N is assigned or there are + no more nlMatrixTopNEntries." + ::= { nlMatrixTopNEntry 1 } + +nlMatrixTopNProtocolDirLocalIndex OBJECT-TYPE + SYNTAX Integer32 (1..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The protocolDirLocalIndex of the network layer protocol of + this entry's network address." + ::= { nlMatrixTopNEntry 2 } + +nlMatrixTopNSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The network layer address of the source host in this + conversation. + + This is represented as an octet string with + specific semantics and length as identified + by the associated nlMatrixTopNProtocolDirLocalIndex. + + For example, if the protocolDirLocalIndex indicates an + encapsulation of ip, this object is encoded as a length + octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { nlMatrixTopNEntry 3 } + +nlMatrixTopNDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + + + "The network layer address of the destination host in this + conversation. + + This is represented as an octet string with + specific semantics and length as identified + by the associated nlMatrixTopNProtocolDirLocalIndex. + + For example, if the nlMatrixTopNProtocolDirLocalIndex + indicates an encapsulation of ip, this object is encoded as a + length octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { nlMatrixTopNEntry 4 } + +nlMatrixTopNPktRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets seen from the source host + to the destination host during this sampling interval, counted + using the rules for counting the nlMatrixSDPkts object. + If the value of nlMatrixTopNControlRateBase is + nlMatrixTopNPkts, this variable will be used to sort this + report." + ::= { nlMatrixTopNEntry 5 } + +nlMatrixTopNReversePktRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets seen from the destination host to the + source host during this sampling interval, counted + using the rules for counting the nlMatrixSDPkts object (note + that the corresponding nlMatrixSDPkts object selected is the + one whose source address is equal to nlMatrixTopNDestAddress + and whose destination address is equal to + nlMatrixTopNSourceAddress.) + + Note that if the value of nlMatrixTopNControlRateBase is equal + to nlMatrixTopNPkts, the sort of topN entries is based + entirely on nlMatrixTopNPktRate, and not on the value of this + object." + ::= { nlMatrixTopNEntry 6 } + +nlMatrixTopNOctetRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + + + STATUS current + DESCRIPTION + "The number of octets seen from the source host + to the destination host during this sampling interval, counted + using the rules for counting the nlMatrixSDOctets object. If + the value of nlMatrixTopNControlRateBase is + nlMatrixTopNOctets, this variable will be used to sort this + report." + ::= { nlMatrixTopNEntry 7 } + +nlMatrixTopNReverseOctetRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets seen from the destination host to the + source host during this sampling interval, counted + using the rules for counting the nlMatrixDSOctets object (note + that the corresponding nlMatrixSDOctets object selected is the + one whose source address is equal to nlMatrixTopNDestAddress + and whose destination address is equal to + nlMatrixTopNSourceAddress.) + + Note that if the value of nlMatrixTopNControlRateBase is equal + to nlMatrixTopNOctets, the sort of topN entries is based + entirely on nlMatrixTopNOctetRate, and not on the value of + this object." + ::= { nlMatrixTopNEntry 8 } + +-- Application Layer Functions +-- +-- The application layer host, matrix, and matrixTopN functions report +-- on protocol usage at the network layer or higher. Note that the +-- use of the term application layer does not imply that only +-- application-layer protocols are counted, rather it means that +-- protocols up to and including the application layer are supported. + +-- +-- Application Layer Host Group +-- +-- Counts the amount of traffic, by protocol, sent from and to each +-- network address discovered by the probe. +-- Implementation of this group requires implementation of the Network +-- Layer Host Group. + +alHostTable OBJECT-TYPE + SYNTAX SEQUENCE OF AlHostEntry + MAX-ACCESS not-accessible + + + STATUS current + DESCRIPTION + "A collection of statistics for a particular protocol from a + particular network address that has been discovered on an + interface of this device. + + The probe will populate this table for all protocols in the + protocol directory table whose value of + protocolDirHostConfig is equal to supportedOn(3), and + will delete any entries whose protocolDirEntry is deleted or + has a protocolDirHostConfig value of supportedOff(2). + + The probe will add to this table all addresses + seen as the source or destination address in all packets with + no MAC errors, and will increment octet and packet counts in + the table for all packets with no MAC errors. Further, + entries will only be added to this table if their address + exists in the nlHostTable and will be deleted from this table + if their address is deleted from the nlHostTable." + ::= { alHost 1 } + +alHostEntry OBJECT-TYPE + SYNTAX AlHostEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the alHostTable. + + The hlHostControlIndex value in the index identifies the + hlHostControlEntry on whose behalf this entry was created. + The first protocolDirLocalIndex value in the index identifies + the network layer protocol of the address. + The nlHostAddress value in the index identifies the network + layer address of this entry. + The second protocolDirLocalIndex value in the index identifies + the protocol that is counted by this entry. + + An example of the indexing in this entry is + alHostOutPkts.1.783495.18.4.128.2.6.6.34" + INDEX { hlHostControlIndex, alHostTimeMark, + protocolDirLocalIndex, nlHostAddress, + protocolDirLocalIndex } -- OTP-1427 + ::= { alHostTable 1 } + +AlHostEntry ::= SEQUENCE { + alHostTimeMark TimeFilter, + alHostInPkts ZeroBasedCounter32, + alHostOutPkts ZeroBasedCounter32, + + + alHostInOctets ZeroBasedCounter32, + alHostOutOctets ZeroBasedCounter32, + alHostCreateTime LastCreateTime +} + +alHostTimeMark OBJECT-TYPE + SYNTAX TimeFilter + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A TimeFilter for this entry. See the TimeFilter textual + convention to see how this works." + ::= { alHostEntry 1 } + +alHostInPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets of this protocol type without errors + transmitted to this address since it was added to the + alHostTable. Note that this is the number of link-layer + packets, so if a single network-layer packet is fragmented + into several link-layer frames, this counter is incremented + several times." + ::= { alHostEntry 2 } + +alHostOutPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets of this protocol type without errors + transmitted by this address since it was added to the + alHostTable. Note that this is the number of link-layer + packets, so if a single network-layer packet is fragmented + into several link-layer frames, this counter is incremented + several times." + ::= { alHostEntry 3 } + +alHostInOctets OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted to this address + of this protocol type since it was added to the + alHostTable (excluding framing bits but including + + + FCS octets), excluding those octets in packets that + contained errors. + + Note this doesn't count just those octets in the particular + protocol frames, but includes the entire packet that contained + the protocol." + ::= { alHostEntry 4 } + +alHostOutOctets OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted by this address + of this protocol type since it was added to the + alHostTable (excluding framing bits but including + FCS octets), excluding those octets in packets that + contained errors. + + Note this doesn't count just those octets in the particular + protocol frames, but includes the entire packet that contained + the protocol." + ::= { alHostEntry 5 } + +alHostCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this entry was last activated. + This can be used by the management station to ensure that the + entry has not been deleted and recreated between polls." + ::= { alHostEntry 6 } + +-- +-- Application Layer Matrix Group +-- +-- Counts the amount of traffic, by protocol, sent between each pair +-- of network addresses discovered by the probe. +-- Implementation of this group requires implementation of the Network +-- Layer Matrix Group. + +alMatrixSDTable OBJECT-TYPE + SYNTAX SEQUENCE OF AlMatrixSDEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of application traffic matrix entries which collect + + + statistics for conversations of a particular protocol between + two network-level addresses. This table is indexed first by + the source address and then by the destination address to make + it convenient to collect all statistics from a particular + address. + + The probe will populate this table for all protocols in the + protocol directory table whose value of + protocolDirMatrixConfig is equal to supportedOn(3), and + will delete any entries whose protocolDirEntry is deleted or + has a protocolDirMatrixConfig value of supportedOff(2). + + The probe will add to this table all pairs of addresses for + all protocols seen in all packets with no MAC errors, and will + increment octet and packet counts in the table for all packets + with no MAC errors. Further, entries will only be added to + this table if their address pair exists in the nlMatrixSDTable + and will be deleted from this table if the address pair is + deleted from the nlMatrixSDTable." + ::= { alMatrix 1 } + +alMatrixSDEntry OBJECT-TYPE + SYNTAX AlMatrixSDEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the alMatrixSDTable. + + The hlMatrixControlIndex value in the index identifies the + hlMatrixControlEntry on whose behalf this entry was created. + The first protocolDirLocalIndex value in the index identifies + the network layer protocol of the nlMatrixSDSourceAddress and + nlMatrixSDDestAddress. + The nlMatrixSDSourceAddress value in the index identifies the + network layer address of the source host in this conversation. + The nlMatrixSDDestAddress value in the index identifies the + network layer address of the destination host in this + conversation. + The second protocolDirLocalIndex value in the index identifies + the protocol that is counted by this entry. + + An example of the indexing of this entry is + alMatrixSDPkts.1.783495.18.4.128.2.6.6.4.128.2.6.7.34" + INDEX { hlMatrixControlIndex, alMatrixSDTimeMark, + protocolDirLocalIndex, + nlMatrixSDSourceAddress, nlMatrixSDDestAddress, + protocolDirLocalIndex } + ::= { alMatrixSDTable 1 } + + +AlMatrixSDEntry ::= SEQUENCE { + alMatrixSDTimeMark TimeFilter, + alMatrixSDPkts ZeroBasedCounter32, + alMatrixSDOctets ZeroBasedCounter32, + alMatrixSDCreateTime LastCreateTime +} + +alMatrixSDTimeMark OBJECT-TYPE + SYNTAX TimeFilter + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A TimeFilter for this entry. See the TimeFilter textual + convention to see how this works." + ::= { alMatrixSDEntry 1 } + +alMatrixSDPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets of this protocol type without errors + transmitted from the source address to the destination address + since this entry was added to the alMatrixSDTable. Note that + this is the number of link-layer packets, so if a single + network-layer packet is fragmented into several link-layer + frames, this counter is incremented several times." + ::= { alMatrixSDEntry 2 } + +alMatrixSDOctets OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets in packets of this protocol type + transmitted from the source address to the destination address + since this entry was added to the alMatrixSDTable (excluding + framing bits but including FCS octets), excluding those octets + in packets that contained errors. + + Note this doesn't count just those octets in the particular + protocol frames, but includes the entire packet that contained + the protocol." + ::= { alMatrixSDEntry 3 } + +alMatrixSDCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + + + STATUS current + DESCRIPTION + "The value of sysUpTime when this entry was last activated. + This can be used by the management station to ensure that the + entry has not been deleted and recreated between polls." + ::= { alMatrixSDEntry 4 } + +-- Traffic matrix tables from destination to source + +alMatrixDSTable OBJECT-TYPE + SYNTAX SEQUENCE OF AlMatrixDSEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of application traffic matrix entries which collect + statistics for conversations of a particular protocol between + two network-level addresses. This table is indexed first by + the destination address and then by the source address to make + it convenient to collect all statistics to a particular + address. + + The probe will populate this table for all protocols in the + protocol directory table whose value of + protocolDirMatrixConfig is equal to supportedOn(3), and + will delete any entries whose protocolDirEntry is deleted or + has a protocolDirMatrixConfig value of supportedOff(2). + + The probe will add to this table all pairs of addresses for + all protocols seen in all packets with no MAC errors, and will + increment octet and packet counts in the table for all packets + with no MAC errors. Further, entries will only be added to + this table if their address pair exists in the nlMatrixDSTable + and will be deleted from this table if the address pair is + deleted from the nlMatrixDSTable." + ::= { alMatrix 2 } + +alMatrixDSEntry OBJECT-TYPE + SYNTAX AlMatrixDSEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the alMatrixDSTable. + + The hlMatrixControlIndex value in the index identifies the + hlMatrixControlEntry on whose behalf this entry was created. + The first protocolDirLocalIndex value in the index identifies + the network layer protocol of the alMatrixDSSourceAddress and + alMatrixDSDestAddress. + + + The nlMatrixDSDestAddress value in the index identifies the + network layer address of the destination host in this + conversation. + The nlMatrixDSSourceAddress value in the index identifies the + network layer address of the source host in this conversation. + The second protocolDirLocalIndex value in the index identifies + the protocol that is counted by this entry. + + An example of the indexing of this entry is + alMatrixDSPkts.1.783495.18.4.128.2.6.7.4.128.2.6.6.34" + INDEX { hlMatrixControlIndex, alMatrixDSTimeMark, + protocolDirLocalIndex, + nlMatrixDSDestAddress, nlMatrixDSSourceAddress, + protocolDirLocalIndex } + ::= { alMatrixDSTable 1 } + +AlMatrixDSEntry ::= SEQUENCE { + alMatrixDSTimeMark TimeFilter, + alMatrixDSPkts ZeroBasedCounter32, + alMatrixDSOctets ZeroBasedCounter32, + alMatrixDSCreateTime LastCreateTime +} + +alMatrixDSTimeMark OBJECT-TYPE + SYNTAX TimeFilter + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A TimeFilter for this entry. See the TimeFilter textual + convention to see how this works." + ::= { alMatrixDSEntry 1 } + +alMatrixDSPkts OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets of this protocol type without errors + transmitted from the source address to the destination address + since this entry was added to the alMatrixDSTable. Note that + this is the number of link-layer packets, so if a single + network-layer packet is fragmented into several link-layer + frames, this counter is incremented several times." + ::= { alMatrixDSEntry 2 } + +alMatrixDSOctets OBJECT-TYPE + SYNTAX ZeroBasedCounter32 + MAX-ACCESS read-only + + + STATUS current + DESCRIPTION + "The number of octets in packets of this protocol type + transmitted from the source address to the destination address + since this entry was added to the alMatrixDSTable (excluding + framing bits but including FCS octets), excluding those octets + in packets that contained errors. + + Note this doesn't count just those octets in the particular + protocol frames, but includes the entire packet that contained + the protocol." + ::= { alMatrixDSEntry 3 } + +alMatrixDSCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this entry was last activated. + This can be used by the management station to ensure that the + entry has not been deleted and recreated between polls." + ::= { alMatrixDSEntry 4 } + +alMatrixTopNControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF AlMatrixTopNControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of parameters that control the creation of a + report of the top N matrix entries according to + a selected metric." + ::= { alMatrix 3 } + +alMatrixTopNControlEntry OBJECT-TYPE + SYNTAX AlMatrixTopNControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the alMatrixTopNControlTable. + + An example of the indexing of this table is + alMatrixTopNControlDuration.3" + INDEX { alMatrixTopNControlIndex } + ::= { alMatrixTopNControlTable 1 } + +AlMatrixTopNControlEntry ::= SEQUENCE { + alMatrixTopNControlIndex Integer32, + alMatrixTopNControlMatrixIndex Integer32, + + + alMatrixTopNControlRateBase INTEGER, + alMatrixTopNControlTimeRemaining Integer32, + alMatrixTopNControlGeneratedReports Counter32, + alMatrixTopNControlDuration Integer32, + alMatrixTopNControlRequestedSize Integer32, + alMatrixTopNControlGrantedSize Integer32, + alMatrixTopNControlStartTime TimeStamp, + alMatrixTopNControlOwner OwnerString, + alMatrixTopNControlStatus RowStatus +} + +alMatrixTopNControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry + in the alMatrixTopNControlTable. Each such + entry defines one top N report prepared for + one interface." + ::= { alMatrixTopNControlEntry 1 } + +alMatrixTopNControlMatrixIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The alMatrix[SD/DS] table for which a top N report will be + prepared on behalf of this entry. The alMatrix[SD/DS] table + is identified by the value of the hlMatrixControlIndex + for that table - that value is used here to identify the + particular table. + + This object may not be modified if the associated + alMatrixTopNControlStatus object is equal to active(1)." + ::= { alMatrixTopNControlEntry 2 } + +alMatrixTopNControlRateBase OBJECT-TYPE + SYNTAX INTEGER { + alMatrixTopNTerminalsPkts(1), + alMatrixTopNTerminalsOctets(2), + alMatrixTopNAllPkts(3), + alMatrixTopNAllOctets(4) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The variable for each alMatrix[SD/DS] entry that the + + + alMatrixTopNEntries are sorted by, as well as the + selector of the view of the matrix table that will be + used. + + The values alMatrixTopNTerminalsPkts and + alMatrixTopNTerminalsOctets cause collection only from + protocols that have no child protocols that are counted. The + values alMatrixTopNAllPkts and alMatrixTopNAllOctets cause + collection from all alMatrix entries. + + This object may not be modified if the associated + alMatrixTopNControlStatus object is equal to active(1)." + ::= { alMatrixTopNControlEntry 3 } + +alMatrixTopNControlTimeRemaining OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The number of seconds left in the report currently + being collected. When this object is modified by + the management station, a new collection is started, + possibly aborting a currently running report. The + new value is used as the requested duration of this + report, and is immediately loaded into the associated + alMatrixTopNControlDuration object. + When the report finishes, the probe will automatically + start another collection with the same initial value + of alMatrixTopNControlTimeRemaining. Thus the management + station may simply read the resulting reports repeatedly, + checking the startTime and duration each time to ensure that a + report was not missed or that the report parameters were not + changed. + + While the value of this object is non-zero, it decrements + by one per second until it reaches zero. At the time + that this object decrements to zero, the report is made + accessible in the alMatrixTopNTable, overwriting any report + that may be there. + + When this object is modified by the management station, any + associated entries in the alMatrixTopNTable shall be deleted. + + (Note that this is a different algorithm than the one used in + the hostTopNTable)." + DEFVAL { 1800 } + ::= { alMatrixTopNControlEntry 4 } + + + +alMatrixTopNControlGeneratedReports OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of reports that have been generated by this entry." + ::= { alMatrixTopNControlEntry 5 } + +alMatrixTopNControlDuration OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of seconds that this report has collected + during the last sampling interval. + + When the associated alMatrixTopNControlTimeRemaining object + is set, this object shall be set by the probe to the + same value and shall not be modified until the next + time the alMatrixTopNControlTimeRemaining is set. + + This value shall be zero if no reports have been + requested for this alMatrixTopNControlEntry." + ::= { alMatrixTopNControlEntry 6 } + +alMatrixTopNControlRequestedSize OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum number of matrix entries requested for this report. + + When this object is created or modified, the probe + should set alMatrixTopNControlGrantedSize as closely to this + object as is possible for the particular probe + implementation and available resources." + DEFVAL { 150 } + ::= { alMatrixTopNControlEntry 7 } + +alMatrixTopNControlGrantedSize OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum number of matrix entries in this report. + + When the associated alMatrixTopNControlRequestedSize object + is created or modified, the probe should set this + + + object as closely to the requested value as is + possible for the particular implementation and + available resources. The probe must not lower this + value except as a result of a set to the associated + alMatrixTopNControlRequestedSize object. + + If the value of alMatrixTopNControlRateBase is equal to + alMatrixTopNTerminalsPkts or alMatrixTopNAllPkts, when the + next topN report is generated, matrix entries with the highest + value of alMatrixTopNPktRate shall be placed in this table in + decreasing order of this rate until there is no more room or + until there are no more matrix entries. + + If the value of alMatrixTopNControlRateBase is equal to + alMatrixTopNTerminalsOctets or alMatrixTopNAllOctets, when the + next topN report is generated, matrix entries with the highest + value of alMatrixTopNOctetRate shall be placed in this table + in decreasing order of this rate until there is no more room + or until there are no more matrix entries. + + It is an implementation-specific matter how entries with the + same value of alMatrixTopNPktRate or alMatrixTopNOctetRate are + sorted. It is also an implementation-specific matter as to + whether or not zero-valued entries are available." + ::= { alMatrixTopNControlEntry 8 } + +alMatrixTopNControlStartTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this top N report was + last started. In other words, this is the time that + the associated alMatrixTopNControlTimeRemaining object + was modified to start the requested report or the time + the report was last automatically (re)started. + + This object may be used by the management station to + determine if a report was missed or not." + ::= { alMatrixTopNControlEntry 9 } + +alMatrixTopNControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + + + ::= { alMatrixTopNControlEntry 10 } + +alMatrixTopNControlStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this alMatrixTopNControlEntry. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value. + + If this object is not equal to active(1), all + associated entries in the alMatrixTopNTable shall be + deleted by the agent." + ::= { alMatrixTopNControlEntry 11 } + +alMatrixTopNTable OBJECT-TYPE + SYNTAX SEQUENCE OF AlMatrixTopNEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of statistics for those application layer matrix + entries that have counted the highest number of octets or + packets." + ::= { alMatrix 4 } + +alMatrixTopNEntry OBJECT-TYPE + SYNTAX AlMatrixTopNEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A conceptual row in the alMatrixTopNTable. + + The alMatrixTopNControlIndex value in the index identifies + the alMatrixTopNControlEntry on whose behalf this entry was + created. + + An example of the indexing of this table is + alMatrixTopNPktRate.3.10" + INDEX { alMatrixTopNControlIndex, alMatrixTopNIndex } + ::= { alMatrixTopNTable 1 } + +AlMatrixTopNEntry ::= SEQUENCE { + alMatrixTopNIndex Integer32, + alMatrixTopNProtocolDirLocalIndex Integer32, + alMatrixTopNSourceAddress OCTET STRING, + alMatrixTopNDestAddress OCTET STRING, + + + alMatrixTopNAppProtocolDirLocalIndex Integer32, + alMatrixTopNPktRate Gauge32, + alMatrixTopNReversePktRate Gauge32, + alMatrixTopNOctetRate Gauge32, + alMatrixTopNReverseOctetRate Gauge32 + } + +alMatrixTopNIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in + the alMatrixTopNTable among those in the same report. + This index is between 1 and N, where N is the + number of entries in this report. + + If the value of alMatrixTopNControlRateBase is equal to + alMatrixTopNTerminalsPkts or alMatrixTopNAllPkts, increasing + values of alMatrixTopNIndex shall be assigned to entries with + decreasing values of alMatrixTopNPktRate until index N is + assigned or there are no more alMatrixTopNEntries. + + If the value of alMatrixTopNControlRateBase is equal to + alMatrixTopNTerminalsOctets or alMatrixTopNAllOctets, + increasing values of alMatrixTopNIndex shall be assigned to + entries with decreasing values of alMatrixTopNOctetRate until + index N is assigned or there are no more alMatrixTopNEntries." + ::= { alMatrixTopNEntry 1 } + +alMatrixTopNProtocolDirLocalIndex OBJECT-TYPE + SYNTAX Integer32 (1..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The protocolDirLocalIndex of the network layer protocol of + this entry's network address." + ::= { alMatrixTopNEntry 2 } + +alMatrixTopNSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The network layer address of the source host in this + conversation. + This is represented as an octet string with + specific semantics and length as identified + + + by the associated alMatrixTopNProtocolDirLocalIndex. + + For example, if the alMatrixTopNProtocolDirLocalIndex + indicates an encapsulation of ip, this object is encoded as a + length octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { alMatrixTopNEntry 3 } + +alMatrixTopNDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The network layer address of the destination host in this + conversation. + + This is represented as an octet string with + specific semantics and length as identified + by the associated alMatrixTopNProtocolDirLocalIndex. + + For example, if the alMatrixTopNProtocolDirLocalIndex + indicates an encapsulation of ip, this object is encoded as a + length octet of 4, followed by the 4 octets of the ip address, + in network byte order." + ::= { alMatrixTopNEntry 4 } + +alMatrixTopNAppProtocolDirLocalIndex OBJECT-TYPE + SYNTAX Integer32 (1..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The type of the protocol counted by this matrix entry." + ::= { alMatrixTopNEntry 5 } + +alMatrixTopNPktRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets seen of this protocol from the source + host to the destination host during this sampling interval, + counted using the rules for counting the alMatrixSDPkts + object. + + If the value of alMatrixTopNControlRateBase is + alMatrixTopNTerminalsPkts or alMatrixTopNAllPkts, this + variable will be used to sort this report." + ::= { alMatrixTopNEntry 6 } + + +alMatrixTopNReversePktRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets seen of this protocol from the + destination host to the source host during this sampling + interval, counted using the rules for counting the + alMatrixDSPkts object (note that the corresponding + alMatrixSDPkts object selected is the one whose source address + is equal to alMatrixTopNDestAddress and whose destination + address is equal to alMatrixTopNSourceAddress.) + + Note that if the value of alMatrixTopNControlRateBase is equal + to alMatrixTopNTerminalsPkts or alMatrixTopNAllPkts, the sort + of topN entries is based entirely on alMatrixTopNPktRate, and + not on the value of this object." + ::= { alMatrixTopNEntry 7 } + +alMatrixTopNOctetRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets seen of this protocol from the source + host to the destination host during this sampling interval, + counted using the rules for counting the alMatrixSDOctets + object. + + If the value of alMatrixTopNControlRateBase is + alMatrixTopNTerminalsOctets or alMatrixTopNAllOctets, this + variable will be used to sort this report." + ::= { alMatrixTopNEntry 8 } + +alMatrixTopNReverseOctetRate OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets seen of this protocol from the + destination host to the source host during this sampling + interval, counted using the rules for counting the + alMatrixDSOctets object (note that the corresponding + alMatrixSDOctets object selected is the one whose source + address is equal to alMatrixTopNDestAddress and whose + destination address is equal to alMatrixTopNSourceAddress.) + + Note that if the value of alMatrixTopNControlRateBase is equal + + + to alMatrixTopNTerminalsOctets or alMatrixTopNAllOctets, the + sort of topN entries is based entirely on + alMatrixTopNOctetRate, and not on the value of this object." + ::= { alMatrixTopNEntry 9 } + +-- +-- User History Collection Group (usrHistory) +-- +-- The usrHistory group combines mechanisms seen in the alarm and +-- history groups to provide user-specified history collection, +-- utilizing two additional control tables and one additional data +-- table. This function has traditionally been done by NMS +-- applications, via periodic polling. The usrHistory group allows +-- this task to be offloaded to an RMON probe. +-- +-- Data (an ASN.1 INTEGER based object) is collected in the same +-- manner as any history data table (e.g. etherHistoryTable) except +-- that the user specifies the MIB instances to be collected. Objects +-- are collected in bucket-groups, with the intent that all MIB +-- instances in the same bucket-group are collected as atomically as +-- possible by the RMON probe. +-- +-- The usrHistoryControlTable is a one-dimensional read-create table. +-- Each row configures a collection of user history buckets, much +-- the same as a historyControlEntry, except that the creation of a +-- row in this table will cause one or more associated instances in +-- the usrHistoryObjectTable to be created. The user specifies the +-- number of bucket elements (rows in the usrHistoryObjectTable) +-- requested, as well as the number of buckets requested. +-- +-- The usrHistoryObjectTable is a 2-d read-write table. +-- Each row configures a single MIB instance to be collected. +-- All rows with the same major index constitute a bucket-group. +-- +-- The usrHistoryTable is a 3-d read-only table containing +-- the data of associated usrHistoryControlEntries. Each +-- entry represents the value of a single MIB instance +-- during a specific sampling interval (or the rate of +-- change during the interval). +-- +-- A sample value is stored in two objects - an absolute value and +-- a status object. This allows numbers from -(2G-1) to +4G to be +-- stored. The status object also indicates whether a sample is +-- valid. This allows data collection to continue if periodic +-- retrieval of a particular instance fails for any reason. +-- +-- Row Creation Order Relationships +-- + + +-- The static nature of the usrHistoryObjectTable creates +-- some row creation/modification issues. The rows in this +-- table need to be set before the associated +-- usrHistoryControlEntry can be activated. +-- +-- Note that the usrHistoryObject entries associated with a +-- particular usrHistoryControlEntry are not required to +-- be active before the control entry is activated. However, +-- the usrHistory data entries associated with an inactive +-- usrHistoryObject entry will be inactive (i.e. +-- usrHistoryValStatus == valueNotAvailable). +-- + +usrHistoryControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF UsrHistoryControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of data-collection configuration entries." + ::= { usrHistory 1 } + +usrHistoryControlEntry OBJECT-TYPE + SYNTAX UsrHistoryControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of parameters that set up a group of user-defined + MIB objects to be sampled periodically (called a + bucket-group). + + For example, an instance of usrHistoryControlInterval + might be named usrHistoryControlInterval.1" + INDEX { usrHistoryControlIndex } + ::= { usrHistoryControlTable 1 } + +UsrHistoryControlEntry ::= SEQUENCE { + usrHistoryControlIndex Integer32, + usrHistoryControlObjects Integer32, + usrHistoryControlBucketsRequested Integer32, + usrHistoryControlBucketsGranted Integer32, + usrHistoryControlInterval Integer32, + usrHistoryControlOwner OwnerString, + usrHistoryControlStatus RowStatus +} + +usrHistoryControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + + + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in the + usrHistoryControlTable. Each such entry defines a + set of samples at a particular interval for a specified + set of MIB instances available from the managed system." + ::= { usrHistoryControlEntry 1 } + +usrHistoryControlObjects OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The number of MIB objects to be collected + in the portion of usrHistoryTable associated with this + usrHistoryControlEntry. + + This object may not be modified if the associated instance + of usrHistoryControlStatus is equal to active(1)." + ::= { usrHistoryControlEntry 2 } + +usrHistoryControlBucketsRequested OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The requested number of discrete time intervals + over which data is to be saved in the part of the + usrHistoryTable associated with this usrHistoryControlEntry. + + When this object is created or modified, the probe + should set usrHistoryControlBucketsGranted as closely to + this object as is possible for the particular probe + implementation and available resources." + DEFVAL { 50 } + ::= { usrHistoryControlEntry 3 } + +usrHistoryControlBucketsGranted OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of discrete sampling intervals + over which data shall be saved in the part of + the usrHistoryTable associated with this + usrHistoryControlEntry. + + When the associated usrHistoryControlBucketsRequested + + + object is created or modified, the probe should set + this object as closely to the requested value as is + possible for the particular probe implementation and + available resources. The probe must not lower this + value except as a result of a modification to the associated + usrHistoryControlBucketsRequested object. + + The associated usrHistoryControlBucketsRequested object + should be set before or at the same time as this object + to allow the probe to accurately estimate the resources + required for this usrHistoryControlEntry. + + There will be times when the actual number of buckets + associated with this entry is less than the value of + this object. In this case, at the end of each sampling + interval, a new bucket will be added to the usrHistoryTable. + + When the number of buckets reaches the value of this object + and a new bucket is to be added to the usrHistoryTable, + the oldest bucket associated with this usrHistoryControlEntry + shall be deleted by the agent so that the new bucket can be + added. + + When the value of this object changes to a value less than + the current value, entries are deleted from the + usrHistoryTable associated with this usrHistoryControlEntry. + Enough of the oldest of these entries shall be deleted by the + agent so that their number remains less than or equal to the + new value of this object. + + When the value of this object changes to a value greater + than the current value, the number of associated usrHistory + entries may be allowed to grow." + ::= { usrHistoryControlEntry 4 } + + +usrHistoryControlInterval OBJECT-TYPE + SYNTAX Integer32 (1..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The interval in seconds over which the data is + sampled for each bucket in the part of the usrHistory + table associated with this usrHistoryControlEntry. + + Because the counters in a bucket may overflow at their + maximum value with no indication, a prudent manager will + take into account the possibility of overflow in any of + + + the associated counters. It is important to consider the + minimum time in which any counter could overflow on a + particular media type and set the usrHistoryControlInterval + object to a value less than this interval. + + This object may not be modified if the associated + usrHistoryControlStatus object is equal to active(1)." + DEFVAL { 1800 } + ::= { usrHistoryControlEntry 5 } + +usrHistoryControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { usrHistoryControlEntry 6 } + +usrHistoryControlStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this variable history control entry. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value. + + If this object is not equal to active(1), all associated + entries in the usrHistoryTable shall be deleted." + ::= { usrHistoryControlEntry 7 } + +-- Object table + +usrHistoryObjectTable OBJECT-TYPE + SYNTAX SEQUENCE OF UsrHistoryObjectEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of data-collection configuration entries." + ::= { usrHistory 2 } + +usrHistoryObjectEntry OBJECT-TYPE + SYNTAX UsrHistoryObjectEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + + + "A list of MIB instances to be sampled periodically. + + Entries in this table are created when an associated + usrHistoryControlObjects object is created. + + The usrHistoryControlIndex value in the index is + that of the associated usrHistoryControlEntry. + + For example, an instance of usrHistoryObjectVariable might be + usrHistoryObjectVariable.1.3" + INDEX { usrHistoryControlIndex, usrHistoryObjectIndex } + ::= { usrHistoryObjectTable 1 } + +UsrHistoryObjectEntry ::= SEQUENCE { + usrHistoryObjectIndex Integer32, + usrHistoryObjectVariable OBJECT IDENTIFIER, + usrHistoryObjectSampleType INTEGER +} + +usrHistoryObjectIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An index used to uniquely identify an entry in the + usrHistoryObject table. Each such entry defines a + MIB instance to be collected periodically." + ::= { usrHistoryObjectEntry 1 } + + +usrHistoryObjectVariable OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The object identifier of the particular variable to be + sampled. + + Only variables that resolve to an ASN.1 primitive type of + Integer32 (Integer32, Counter, Gauge, or TimeTicks) may be + sampled. + + Because SNMP access control is articulated entirely in terms + of the contents of MIB views, no access control mechanism + exists that can restrict the value of this object to identify + only those objects that exist in a particular MIB view. + Because there is thus no acceptable means of restricting the + read access that could be obtained through the user history + + + mechanism, the probe must only grant write access to this + object in those views that have read access to all objects on + the probe. + + During a set operation, if the supplied variable name is not + available in the selected MIB view, a badValue error must be + returned. + + This object may not be modified if the associated + usrHistoryControlStatus object is equal to active(1)." + ::= { usrHistoryObjectEntry 2 } + +usrHistoryObjectSampleType OBJECT-TYPE + SYNTAX INTEGER { + absoluteValue(1), + deltaValue(2) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The method of sampling the selected variable for storage in + the usrHistoryTable. + + If the value of this object is absoluteValue(1), the value of + the selected variable will be copied directly into the history + bucket. + + If the value of this object is deltaValue(2), the value of the + selected variable at the last sample will be subtracted from + the current value, and the difference will be stored in the + history bucket. If the associated usrHistoryObjectVariable + instance could not be obtained at the previous sample + interval, then a delta sample is not possible, and the value + of the associated usrHistoryValStatus object for this interval + will be valueNotAvailable(1). + + This object may not be modified if the associated + usrHistoryControlStatus object is equal to active(1)." + ::= { usrHistoryObjectEntry 3 } + +-- data table + +usrHistoryTable OBJECT-TYPE + SYNTAX SEQUENCE OF UsrHistoryEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of user defined history entries." + + + ::= { usrHistory 3 } + +usrHistoryEntry OBJECT-TYPE + SYNTAX UsrHistoryEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A historical sample of user-defined variables. This sample + is associated with the usrHistoryControlEntry which set up the + parameters for a regular collection of these samples. + + The usrHistoryControlIndex value in the index identifies the + usrHistoryControlEntry on whose behalf this entry was created. + + The usrHistoryObjectIndex value in the index identifies the + usrHistoryObjectEntry on whose behalf this entry was created. + + For example, an instance of usrHistoryAbsValue, which represents + the 14th sample of a variable collected as specified by + usrHistoryControlEntry.1 and usrHistoryObjectEntry.1.5, + would be named usrHistoryAbsValue.1.14.5" + INDEX { usrHistoryControlIndex, usrHistorySampleIndex, + usrHistoryObjectIndex } + ::= { usrHistoryTable 1 } + +UsrHistoryEntry ::= SEQUENCE { + usrHistorySampleIndex Integer32, + usrHistoryIntervalStart TimeStamp, + usrHistoryIntervalEnd TimeStamp, + usrHistoryAbsValue Gauge32, + usrHistoryValStatus INTEGER +} + +usrHistorySampleIndex OBJECT-TYPE + SYNTAX Integer32 (1..2147483647) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An index that uniquely identifies the particular sample this + entry represents among all samples associated with the same + usrHistoryControlEntry. This index starts at 1 and increases + by one as each new sample is taken." + ::= { usrHistoryEntry 1 } + +usrHistoryIntervalStart OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + + + DESCRIPTION + "The value of sysUpTime at the start of the interval over + which this sample was measured. If the probe keeps track of + the time of day, it should start the first sample of the + history at a time such that when the next hour of the day + begins, a sample is started at that instant. + + Note that following this rule may require the probe to delay + collecting the first sample of the history, as each sample + must be of the same interval. Also note that the sample which + is currently being collected is not accessible in this table + until the end of its interval." + ::= { usrHistoryEntry 2 } + +usrHistoryIntervalEnd OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the end of the interval over which + this sample was measured." + ::= { usrHistoryEntry 3 } + +usrHistoryAbsValue OBJECT-TYPE + SYNTAX Gauge32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The absolute value (i.e. unsigned value) of the + user-specified statistic during the last sampling period. The + value during the current sampling period is not made available + until the period is completed. + + To obtain the true value for this sampling interval, the + associated instance of usrHistoryValStatus must be checked, + and usrHistoryAbsValue adjusted as necessary. + + If the MIB instance could not be accessed during the sampling + interval, then this object will have a value of zero and the + associated instance of usrHistoryValStatus will be set to + 'valueNotAvailable(1)'." + ::= { usrHistoryEntry 4 } + + +usrHistoryValStatus OBJECT-TYPE + SYNTAX INTEGER { + valueNotAvailable(1), + valuePositive(2), + + + valueNegative(3) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This object indicates the validity and sign of the data in + the associated instance of usrHistoryAbsValue. + + If the MIB instance could not be accessed during the sampling + interval, then 'valueNotAvailable(1)' will be returned. + + If the sample is valid and actual value of the sample is + greater than or equal to zero then 'valuePositive(2)' is + returned. + + If the sample is valid and the actual value of the sample is + less than zero, 'valueNegative(3)' will be returned. The + associated instance of usrHistoryAbsValue should be multiplied + by -1 to obtain the true sample value." + ::= { usrHistoryEntry 5 } + +-- The Probe Configuration Group +-- +-- This group controls the configuration of various operating +-- parameters of the probe. + +ControlString ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "This data type is used to communicate with a modem or a + serial data switch. A ControlString contains embedded + commands to control how the device will interact with the + remote device through the serial interface. Commands are + represented as two character sequences beginning with + the `^' character. + + The following commands are recognized by the device (note + that command characters are case sensitive): + + ^s Send string that follows which is terminated by the + next command or the end of string. + ^c Delay for the number of seconds that follows. Toss + out any data received rather than storing it in a + buffer for parsing. + ^t Set timeout to the value represented by the decimal + digits that follow. The default timeout is 20 + seconds. Note that this timeout may be overridden + by a smaller serialTimeout configured for the + + + associated serial interface (see serialConfigTable). + ^w Wait for the reply string that follows which is + terminated by the next command or the end of string. + Partial and case insensitive matching is applied, ie. + if the reply string (any case combination) is found + anywhere in the received string, then the a match is + found. If the current timeout elapses without a match, + then the remaining control string is ignored. + ^! The ^ character. + ^d Delay the number of seconds specified by the decimal + digits that follow. + ^b Send break for the number of milliseconds specified by + the decimal digits that follow. If no digits follow, + break will be enforced for 250 milliseconds by default. + + The following ASCII control characters may be inserted into + the `^s' send string or the `^w' reply string: + + ^@ 0x00 + ^A 0x01 + .. + ^M 0x0D + .. + ^Z 0x1A + ^[ 0x1B + ^ 0x1C + ^] 0x1D + ^^ 0x1E + ^_ 0x1F + + Binary data may also be inserted into the data stream. The + control sequence for each byte of binary data is ^0x##, where + ## is the hexadecimal representation of the data byte. Two + ASCII characters (0-9, a-f, A-F) must follow the `^0x' + control prefix. For example, `^0x0D^0x0A' is interpreted as a + carriage return followed by a line feed." + SYNTAX DisplayString + +probeCapabilities OBJECT-TYPE + SYNTAX BITS { + etherStats(0), + historyControl(1), + etherHistory(2), + alarm(3), + hosts(4), + hostTopN(5), + matrix(6), + filter(7), + + + capture(8), + event(9), + tokenRingMLStats(10), + tokenRingPStats(11), + tokenRingMLHistory(12), + tokenRingPHistory(13), + ringStation(14), + ringStationOrder(15), + ringStationConfig(16), + sourceRouting(17), + protocolDirectory(18), + protocolDistribution(19), + addressMapping(20), + nlHost(21), + nlMatrix(22), + alHost(23), + alMatrix(24), + usrHistory(25), + probeConfig(26) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An indication of the RMON MIB groups supported + on at least one interface by this probe." + ::= { probeConfig 1 } + +probeSoftwareRev OBJECT-TYPE + SYNTAX DisplayString (SIZE(0..15)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The software revision of this device. This string will have + a zero length if the revision is unknown." + ::= { probeConfig 2 } + +probeHardwareRev OBJECT-TYPE + SYNTAX DisplayString (SIZE(0..31)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The hardware revision of this device. This string will have + a zero length if the revision is unknown." + ::= { probeConfig 3 } + +probeDateTime OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0 | 8 | 11)) + MAX-ACCESS read-write + + + STATUS current + DESCRIPTION + "Probe's current date and time. + + field octets contents range + ----- ------ -------- ----- + 1 1-2 year 0..65536 + 2 3 month 1..12 + 3 4 day 1..31 + 4 5 hour 0..23 + 5 6 minutes 0..59 + 6 7 seconds 0..60 + (use 60 for leap-second) + 7 8 deci-seconds 0..9 + 8 9 direction from UTC '+' / '-' + 9 10 hours from UTC 0..11 + 10 11 minutes from UTC 0..59 + + For example, Tuesday May 26, 1992 at 1:30:15 PM + EDT would be displayed as: + + 1992-5-26,13:30:15.0,-4:0 + + Note that if only local time is known, then + timezone information (fields 8-10) is not + present, and if no time information is known, the null + string is returned." + ::= { probeConfig 4 } + +probeResetControl OBJECT-TYPE + SYNTAX INTEGER { + running(1), + warmBoot(2), + coldBoot(3) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Setting this object to warmBoot(2) causes the device to + restart the application software with current configuration + parameters saved in non-volatile memory. Setting this + object to coldBoot(3) causes the device to reinitialize + configuration parameters in non-volatile memory to default + values and restart the application software. When the device + is running normally, this variable has a value of + running(1)." + ::= { probeConfig 5 } + + + +-- The following download objects do not restrict an implementation +-- from implementing additional download mechanisms (controlled in an +-- implementation-specific manner). Further, in the case where the RMON +-- agent shares a processor with other types of systems, the +-- implementation is not required to download those non-RMON functions +-- with this mechanism. + +probeDownloadFile OBJECT-TYPE + SYNTAX DisplayString (SIZE(0..127)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The file name to be downloaded from the TFTP server when a + download is next requested via this MIB. This value is set to + the zero length string when no file name has been specified." + ::= { probeConfig 6 } + +probeDownloadTFTPServer OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The IP address of the TFTP server that contains the boot + image to load when a download is next requested via this MIB. + This value is set to `0.0.0.0' when no IP address has been + specified." + ::= { probeConfig 7 } + +probeDownloadAction OBJECT-TYPE + SYNTAX INTEGER { + notDownloading(1), + downloadToPROM(2), + downloadToRAM(3) + } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "When this object is set to downloadToRAM(2) or + downloadToPROM(3), the device will discontinue its + normal operation and begin download of the image specified + by probeDownloadFile from the server specified by + probeDownloadTFTPServer using the TFTP protocol. If + downloadToRAM(2) is specified, the new image is copied + to RAM only (the old image remains unaltered in the flash + EPROM). If downloadToPROM(3) is specified + the new image is written to the flash EPROM + memory after its checksum has been verified to be correct. + When the download process is completed, the device will + + + warm boot to restart the newly loaded application. + When the device is not downloading, this object will have + a value of notDownloading(1)." + ::= { probeConfig 8 } + +probeDownloadStatus OBJECT-TYPE + SYNTAX INTEGER { + downloadSuccess(1), + downloadStatusUnknown(2), + downloadGeneralError(3), + downloadNoResponseFromServer(4), + downloadChecksumError(5), + downloadIncompatibleImage(6), + downloadTftpFileNotFound(7), + downloadTftpAccessViolation(8) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The status of the last download procedure, if any. This + object will have a value of downloadStatusUnknown(2) if no + download process has been performed." + ::= { probeConfig 9 } + +serialConfigTable OBJECT-TYPE + SYNTAX SEQUENCE OF SerialConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table of serial interface configuration entries. This data + will be stored in non-volatile memory and preserved across + probe resets or power loss." + ::= { probeConfig 10 } + +serialConfigEntry OBJECT-TYPE + SYNTAX SerialConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of configuration parameters for a particular + serial interface on this device. If the device has no serial + interfaces, this table is empty. + + The index is composed of the ifIndex assigned to this serial + line interface." + INDEX { ifIndex } + ::= { serialConfigTable 1 } + + + +SerialConfigEntry ::= SEQUENCE { + serialMode INTEGER, + serialProtocol INTEGER, + serialTimeout Integer32 (1..65535), + serialModemInitString ControlString (SIZE (0..255)), + serialModemHangUpString ControlString (SIZE (0..255)), + serialModemConnectResp DisplayString (SIZE (0..255)), + serialModemNoConnectResp DisplayString (SIZE (0..255)), + serialDialoutTimeout Integer32 (1..65535), + serialStatus RowStatus +} + +serialMode OBJECT-TYPE + SYNTAX INTEGER { + direct(1), + modem(2) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The type of incoming connection to expect on this serial + interface." + DEFVAL { direct } + ::= { serialConfigEntry 1 } + +serialProtocol OBJECT-TYPE + SYNTAX INTEGER { + other(1), + slip(2), + ppp(3) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The type of data link encapsulation to be used on this + serial interface." + DEFVAL { slip } + ::= { serialConfigEntry 2 } + +serialTimeout OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This timeout value is used when the Management Station has + initiated the conversation over the serial link. This variable + represents the number of seconds of inactivity allowed before + terminating the connection on this serial interface. Use the + + + serialDialoutTimeout in the case where the probe has initiated + the connection for the purpose of sending a trap." + DEFVAL { 300 } + ::= { serialConfigEntry 3 } + +serialModemInitString OBJECT-TYPE + SYNTAX ControlString (SIZE (0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A control string which controls how a modem attached to this + serial interface should be initialized. The initialization + is performed once during startup and again after each + connection is terminated if the associated serialMode has the + value of modem(2). + + A control string that is appropriate for a wide variety of + modems is: '^s^MATE0Q0V1X4 S0=1 S2=43^M'." + ::= { serialConfigEntry 4 } + +serialModemHangUpString OBJECT-TYPE + SYNTAX ControlString (SIZE (0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A control string which specifies how to disconnect a modem + connection on this serial interface. This object is only + meaningful if the associated serialMode has the value + of modem(2). + A control string that is appropriate for a wide variety of + modems is: '^d2^s+++^d2^sATH0^M^d2'." + ::= { serialConfigEntry 5 } + +serialModemConnectResp OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "An ASCII string containing substrings that describe the + expected modem connection response code and associated bps + rate. The substrings are delimited by the first character + in the string, for example: + /CONNECT/300/CONNECT 1200/1200/CONNECT 2400/2400/ + CONNECT 4800/4800/CONNECT 9600/9600 + will be interpreted as: + response code bps rate + CONNECT 300 + CONNECT 1200 1200 + + + CONNECT 2400 2400 + CONNECT 4800 4800 + CONNECT 9600 9600 + The agent will use the information in this string to adjust + the bps rate of this serial interface once a modem connection + is established. + + A value that is appropriate for a wide variety of modems is: + '/CONNECT/300/CONNECT 1200/1200/CONNECT 2400/2400/ + CONNECT 4800/4800/CONNECT 9600/9600/CONNECT 14400/14400/ + CONNECT 19200/19200/CONNECT 38400/38400/'." + ::= { serialConfigEntry 6 } + +serialModemNoConnectResp OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "An ASCII string containing response codes that may be + generated by a modem to report the reason why a connection + attempt has failed. The response codes are delimited by + the first character in the string, for example: + /NO CARRIER/BUSY/NO DIALTONE/NO ANSWER/ERROR/ + If one of these response codes is received via this serial + interface while attempting to make a modem connection, + the agent will issue the hang up command as specified by + serialModemHangUpString. + + A value that is appropriate for a wide variety of modems is: + '/NO CARRIER/BUSY/NO DIALTONE/NO ANSWER/ERROR/'." + ::= { serialConfigEntry 7 } + +serialDialoutTimeout OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This timeout value is used when the probe initiates the + serial connection with the intention of contacting a + management station. This variable represents the number + of seconds of inactivity allowed before terminating the + connection on this serial interface." + DEFVAL { 20 } + ::= { serialConfigEntry 8 } + +serialStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + + + STATUS current + DESCRIPTION + "The status of this serialConfigEntry. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value." + ::= { serialConfigEntry 9 } + +netConfigTable OBJECT-TYPE + SYNTAX SEQUENCE OF NetConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table of netConfigEntries." + ::= { probeConfig 11 } + +netConfigEntry OBJECT-TYPE + SYNTAX NetConfigEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of configuration parameters for a particular + network interface on this device. If the device has no network + interface, this table is empty. + + The index is composed of the ifIndex assigned to the + corresponding interface." + INDEX { ifIndex } + ::= { netConfigTable 1 } + +NetConfigEntry ::= SEQUENCE { + netConfigIPAddress IpAddress, + netConfigSubnetMask IpAddress, + netConfigStatus RowStatus +} + +netConfigIPAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The IP address of this Net interface. The default value + for this object is 0.0.0.0. If either the netConfigIPAddress + or netConfigSubnetMask are 0.0.0.0, then when the device + boots, it may use BOOTP to try to figure out what these + values should be. If BOOTP fails, before the device + can talk on the network, this value must be configured + (e.g., through a terminal attached to the device). If BOOTP is + + + used, care should be taken to not send BOOTP broadcasts too + frequently and to eventually send very infrequently if no + replies are received." + ::= { netConfigEntry 1 } + +netConfigSubnetMask OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The subnet mask of this Net interface. The default value + for this object is 0.0.0.0. If either the netConfigIPAddress + or netConfigSubnetMask are 0.0.0.0, then when the device + boots, it may use BOOTP to try to figure out what these + values should be. If BOOTP fails, before the device + can talk on the network, this value must be configured + (e.g., through a terminal attached to the device). If BOOTP is + used, care should be taken to not send BOOTP broadcasts too + frequently and to eventually send very infrequently if no + replies are received." + ::= { netConfigEntry 2 } + +netConfigStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this netConfigEntry. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value." + ::= { netConfigEntry 3 } + +netDefaultGateway OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The IP Address of the default gateway. If this value is + undefined or unknown, it shall have the value 0.0.0.0." + ::= { probeConfig 12 } + +-- Trap Destination Table +-- +-- This table defines the destination addresses for traps generated +-- from the device. This table maps a community to one or more trap +-- destination entries. +-- + + +-- The same trap will be sent to all destinations specified in the +-- entries that have the same trapDestCommunity as the eventCommunity +-- (as defined by RMON MIB). Information in this table will be stored +-- in non-volatile memory. If the device has gone through a hard +-- restart, this information will be reset to its default state. + +trapDestTable OBJECT-TYPE + SYNTAX SEQUENCE OF TrapDestEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of trap destination entries." + ::= { probeConfig 13 } + +trapDestEntry OBJECT-TYPE + SYNTAX TrapDestEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This entry includes a destination IP address to which to send + traps for this community." + INDEX { trapDestIndex } + ::= { trapDestTable 1 } + +TrapDestEntry ::= SEQUENCE { + trapDestIndex Integer32, + trapDestCommunity OCTET STRING, + trapDestProtocol INTEGER, + trapDestAddress OCTET STRING, + trapDestOwner OwnerString, + trapDestStatus RowStatus +} + +trapDestIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A value that uniquely identifies this trapDestEntry." + ::= { trapDestEntry 1 } + +trapDestCommunity OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(0..127)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A community to which this destination address belongs. + This entry is associated with any eventEntries in the RMON + + + MIB whose value of eventCommunity is equal to the value of + this object. Every time an associated event entry sends a + trap due to an event, that trap will be sent to each + address in the trapDestTable with a trapDestCommunity equal to + eventCommunity. + + This object may not be modified if the associated + trapDestStatus object is equal to active(1)." + ::= { trapDestEntry 2 } + +trapDestProtocol OBJECT-TYPE + SYNTAX INTEGER { + ip(1), + ipx(2) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The protocol with which to send this trap." + ::= { trapDestEntry 3 } + +trapDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The address to send traps on behalf of this entry. + + If the associated trapDestProtocol object is equal to ip(1), + the encoding of this object is the same as the snmpUDPAddress + textual convention in [RFC1906]: + -- for a SnmpUDPAddress of length 6: + -- + -- octets contents encoding + -- 1-4 IP-address network-byte order + -- 5-6 UDP-port network-byte order + + If the associated trapDestProtocol object is equal to ipx(2), + the encoding of this object is the same as the snmpIPXAddress + textual convention in [RFC1906]: + -- for a SnmpIPXAddress of length 12: + -- + -- octets contents encoding + -- 1-4 network-number network-byte order + -- 5-10 physical-address network-byte order + -- 11-12 socket-number network-byte order + + This object may not be modified if the associated + + + trapDestStatus object is equal to active(1)." + ::= { trapDestEntry 4 } + +trapDestOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { trapDestEntry 5 } + +trapDestStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this trap destination entry. + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value." + ::= { trapDestEntry 6 } + +-- Serial Connection Table +-- +-- The device may communicate with a management station using +-- SLIP. In order for the device to send traps via SLIP, it must +-- be able to initiate a connection over the serial interface. The +-- serialConnectionTable stores the parameters for such connection +-- initiation. + +serialConnectionTable OBJECT-TYPE + SYNTAX SEQUENCE OF SerialConnectionEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of serialConnectionEntries." + ::= { probeConfig 14 } + +serialConnectionEntry OBJECT-TYPE + SYNTAX SerialConnectionEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Configuration for a SLIP link over a serial line." + INDEX { serialConnectIndex } + ::= { serialConnectionTable 1 } + + + +SerialConnectionEntry ::= SEQUENCE { + serialConnectIndex Integer32, + serialConnectDestIpAddress IpAddress, + serialConnectType INTEGER, + serialConnectDialString ControlString, + serialConnectSwitchConnectSeq ControlString, + serialConnectSwitchDisconnectSeq ControlString, + serialConnectSwitchResetSeq ControlString, + serialConnectOwner OwnerString, + serialConnectStatus RowStatus +} + +serialConnectIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A value that uniquely identifies this serialConnection + entry." + ::= { serialConnectionEntry 1 } + +serialConnectDestIpAddress OBJECT-TYPE + SYNTAX IpAddress + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The IP Address that can be reached at the other end of this + serial connection. + This object may not be modified if the associated + serialConnectStatus object is equal to active(1)." + ::= { serialConnectionEntry 2 } + + +serialConnectType OBJECT-TYPE + SYNTAX INTEGER { + direct(1), + modem(2), + switch(3), + modemSwitch(4) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The type of outgoing connection to make. If this object + has the value direct(1), then a direct serial connection + is assumed. If this object has the value modem(2), + then serialConnectDialString will be used to make a modem + connection. If this object has the value switch(3), + + + then serialConnectSwitchConnectSeq will be used to establish + the connection over a serial data switch, and + serialConnectSwitchDisconnectSeq will be used to terminate + the connection. If this object has the value + modem-switch(4), then a modem connection will be made first + followed by the switch connection. + + This object may not be modified if the associated + serialConnectStatus object is equal to active(1)." + + DEFVAL { direct } + ::= { serialConnectionEntry 3 } + +serialConnectDialString OBJECT-TYPE + SYNTAX ControlString (SIZE(0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A control string which specifies how to dial the phone + number in order to establish a modem connection. The + string should include dialing prefix and suffix. For + example: ``^s^MATD9,888-1234^M'' will instruct the Probe + to send a carriage return followed by the dialing prefix + ``ATD'', the phone number ``9,888-1234'', and a carriage + return as the dialing suffix. + This object may not be modified if the associated + serialConnectStatus object is equal to active(1)." + ::= { serialConnectionEntry 4 } + +serialConnectSwitchConnectSeq OBJECT-TYPE + SYNTAX ControlString (SIZE(0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A control string which specifies how to establish a + data switch connection. + This object may not be modified if the associated + serialConnectStatus object is equal to active(1)." + ::= { serialConnectionEntry 5 } + +serialConnectSwitchDisconnectSeq OBJECT-TYPE + SYNTAX ControlString (SIZE(0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A control string which specifies how to terminate a + data switch connection. + This object may not be modified if the associated + + + serialConnectStatus object is equal to active(1)." + ::= { serialConnectionEntry 6 } + +serialConnectSwitchResetSeq OBJECT-TYPE + SYNTAX ControlString (SIZE(0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A control string which specifies how to reset a data + switch in the event of a timeout. + This object may not be modified if the associated + serialConnectStatus object is equal to active(1)." + ::= { serialConnectionEntry 7 } + +serialConnectOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { serialConnectionEntry 8 } + +serialConnectStatus OBJECT-TYPE + SYNTAX RowStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this serialConnectionEntry. + + If the manager attempts to set this object to active(1) when + the serialConnectType is set to modem(2) or modem-switch(4) + and the serialConnectDialString is a zero-length string or + cannot be correctly parsed as a ConnectString, the set + request will be rejected with badValue(3). + + If the manager attempts to set this object to active(1) when + the serialConnectType is set to switch(3) or modem-switch(4) + and the serialConnectSwitchConnectSeq, + the serialConnectSwitchDisconnectSeq, or + the serialConnectSwitchResetSeq are zero-length strings + or cannot be correctly parsed as ConnectStrings, the set + request will be rejected with badValue(3). + + An entry may not exist in the active state unless all + objects in the entry have an appropriate value." + ::= { serialConnectionEntry 9 } + + + +-- +-- Extensions to the RMON 1 MIB for RMON 2 devices +-- +-- These extensions include the standard LastCreateTime Textual +-- Convention for all control tables, as well as an augmentation of +-- the filter entry that provides variable-length offsets into +-- packets. + + +-- Each of the following, except for filterDroppedFrames, is a +-- read-only object which, if implemented, automatically appears when +-- the RMON1 row it is associated with is created. + +etherStats2Table OBJECT-TYPE + SYNTAX SEQUENCE OF EtherStats2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + ::= { statistics 4 } + +etherStats2Entry OBJECT-TYPE + SYNTAX EtherStats2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + AUGMENTS { etherStatsEntry } + ::= { etherStats2Table 1 } + +EtherStats2Entry ::= SEQUENCE { + etherStatsDroppedFrames Counter32, + etherStatsCreateTime LastCreateTime +} + +etherStatsDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + + + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { etherStats2Entry 1 } + +etherStatsCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this control entry was last + activated. This can be used by the management station to + ensure that the table has not been deleted and recreated + between polls." + ::= { etherStats2Entry 2 } + +historyControl2Table OBJECT-TYPE + SYNTAX SEQUENCE OF HistoryControl2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + ::= { history 5 } + +historyControl2Entry OBJECT-TYPE + SYNTAX HistoryControl2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + AUGMENTS { historyControlEntry } + ::= { historyControl2Table 1 } + +HistoryControl2Entry ::= SEQUENCE { + historyControlDroppedFrames Counter32 +} + +historyControlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + + + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { historyControl2Entry 1 } + +hostControl2Table OBJECT-TYPE + SYNTAX SEQUENCE OF HostControl2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + ::= { hosts 4 } + +hostControl2Entry OBJECT-TYPE + SYNTAX HostControl2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + AUGMENTS { hostControlEntry } + ::= { hostControl2Table 1 } + +HostControl2Entry ::= SEQUENCE { + hostControlDroppedFrames Counter32, + hostControlCreateTime LastCreateTime +} + +hostControlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + + + ::= { hostControl2Entry 1 } + +hostControlCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this control entry was last + activated. This can be used by the management station to + ensure that the table has not been deleted and recreated + between polls." + ::= { hostControl2Entry 2 } + +matrixControl2Table OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixControl2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + ::= { matrix 4 } + +matrixControl2Entry OBJECT-TYPE + SYNTAX MatrixControl2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + AUGMENTS { matrixControlEntry } + ::= { matrixControl2Table 1 } + +MatrixControl2Entry ::= SEQUENCE { + matrixControlDroppedFrames Counter32, + matrixControlCreateTime LastCreateTime +} + +matrixControlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + + + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { matrixControl2Entry 1 } + +matrixControlCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this control entry was last + activated. This can be used by the management station to + ensure that the table has not been deleted and recreated + between polls." + ::= { matrixControl2Entry 2 } + +channel2Table OBJECT-TYPE + SYNTAX SEQUENCE OF Channel2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + ::= { filter 3 } + +channel2Entry OBJECT-TYPE + SYNTAX Channel2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + AUGMENTS { channelEntry } + ::= { channel2Table 1 } + +Channel2Entry ::= SEQUENCE { + channelDroppedFrames Counter32, + channelCreateTime LastCreateTime +} + +channelDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + + + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { channel2Entry 1 } + +channelCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this control entry was last + activated. This can be used by the management station to + ensure that the table has not been deleted and recreated + between polls." + ::= { channel2Entry 2 } + +tokenRingMLStats2Table OBJECT-TYPE + SYNTAX SEQUENCE OF TokenRingMLStats2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + ::= { statistics 5 } + +tokenRingMLStats2Entry OBJECT-TYPE + SYNTAX TokenRingMLStats2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + AUGMENTS { tokenRingMLStatsEntry } + ::= { tokenRingMLStats2Table 1 } + +TokenRingMLStats2Entry ::= SEQUENCE { + tokenRingMLStatsDroppedFrames Counter32, + tokenRingMLStatsCreateTime LastCreateTime +} + +tokenRingMLStatsDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + + + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { tokenRingMLStats2Entry 1 } + +tokenRingMLStatsCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this control entry was last activated. + This can be used by the management station to ensure that the + table has not been deleted and recreated between polls." + ::= { tokenRingMLStats2Entry 2 } + +tokenRingPStats2Table OBJECT-TYPE + SYNTAX SEQUENCE OF TokenRingPStats2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + ::= { statistics 6 } + +tokenRingPStats2Entry OBJECT-TYPE + SYNTAX TokenRingPStats2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + AUGMENTS { tokenRingPStatsEntry } + ::= { tokenRingPStats2Table 1 } + +TokenRingPStats2Entry ::= SEQUENCE { + tokenRingPStatsDroppedFrames Counter32, + tokenRingPStatsCreateTime LastCreateTime +} + +tokenRingPStatsDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + + + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { tokenRingPStats2Entry 1 } + +tokenRingPStatsCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this control entry was last activated. + This can be used by the management station to ensure that the + table has not been deleted and recreated between polls." + ::= { tokenRingPStats2Entry 2 } + +ringStationControl2Table OBJECT-TYPE + SYNTAX SEQUENCE OF RingStationControl2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + ::= { tokenRing 7 } + +ringStationControl2Entry OBJECT-TYPE + SYNTAX RingStationControl2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + AUGMENTS { ringStationControlEntry } + ::= { ringStationControl2Table 1 } + +RingStationControl2Entry ::= SEQUENCE { + ringStationControlDroppedFrames Counter32, + ringStationControlCreateTime LastCreateTime +} + + +ringStationControlDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { ringStationControl2Entry 1 } + +ringStationControlCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this control entry was last activated. + This can be used by the management station to ensure that the + table has not been deleted and recreated between polls." + ::= { ringStationControl2Entry 2 } + +sourceRoutingStats2Table OBJECT-TYPE + SYNTAX SEQUENCE OF SourceRoutingStats2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + ::= { tokenRing 8 } + +sourceRoutingStats2Entry OBJECT-TYPE + SYNTAX SourceRoutingStats2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Contains the RMON-2 augmentations to RMON-1." + AUGMENTS { sourceRoutingStatsEntry } + ::= { sourceRoutingStats2Table 1 } + +SourceRoutingStats2Entry ::= SEQUENCE { + sourceRoutingStatsDroppedFrames Counter32, + + + sourceRoutingStatsCreateTime LastCreateTime +} + +sourceRoutingStatsDroppedFrames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of frames which were received by the probe + and therefore not accounted for in the *StatsDropEvents, but + for which the probe chose not to count for this entry for + whatever reason. Most often, this event occurs when the probe + is out of some resources and decides to shed load from this + collection. + + This count does not include packets that were not counted + because they had MAC-layer errors. + + Note that, unlike the dropEvents counter, this number is the + exact number of frames dropped." + ::= { sourceRoutingStats2Entry 1 } + +sourceRoutingStatsCreateTime OBJECT-TYPE + SYNTAX LastCreateTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this control entry was last activated. + This can be used by the management station to ensure that the + table has not been deleted and recreated between polls." + ::= { sourceRoutingStats2Entry 2 } + +filter2Table OBJECT-TYPE + SYNTAX SEQUENCE OF Filter2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Provides a variable-length packet filter feature to the + RMON-1 filter table." + ::= { filter 4 } + +filter2Entry OBJECT-TYPE + SYNTAX Filter2Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Provides a variable-length packet filter feature to the + RMON-1 filter table." + + + AUGMENTS { filterEntry } + ::= { filter2Table 1 } + +Filter2Entry ::= SEQUENCE { + filterProtocolDirDataLocalIndex Integer32, + filterProtocolDirLocalIndex Integer32 +} + +filterProtocolDirDataLocalIndex OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "When this object is set to a non-zero value, the filter that + it is associated with performs the following operations on + every packet: + + 1) - If the packet doesn't match the protocol directory entry + identified by this object, discard the packet and exit + (i.e., discard the packet if it is not of the identified + protocol). + 2) - If the associated filterProtocolDirLocalIndex is non-zero + and the packet doesn't match the protocol directory + entry identified by that object, discard the packet and + exit + 3) - If the packet matches, perform the regular filter + algorithm as if the beginning of this named protocol is + the beginning of the packet, potentially applying the + filterOffset value to move further into the packet." + DEFVAL { 0 } + ::= { filter2Entry 1 } + +filterProtocolDirLocalIndex OBJECT-TYPE + SYNTAX Integer32 (0..2147483647) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "When this object is set to a non-zero value, the filter that + it is associated with will discard the packet if the packet + doesn't match this protocol directory entry." + DEFVAL { 0 } + ::= { filter2Entry 2 } + +-- Conformance Macros + +rmon2MIBCompliances OBJECT IDENTIFIER ::= { rmonConformance 1 } +rmon2MIBGroups OBJECT IDENTIFIER ::= { rmonConformance 2 } + + + +rmon2MIBCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "Describes the requirements for conformance to + the RMON2 MIB" + MODULE -- this module + MANDATORY-GROUPS { protocolDirectoryGroup, + protocolDistributionGroup, + addressMapGroup, + nlHostGroup, + nlMatrixGroup, + usrHistoryGroup, + probeInformationGroup } + + GROUP rmon1EnhancementGroup + DESCRIPTION + "The rmon1EnhancementGroup is mandatory for systems which + implement RMON [RFC1757]" + ::= { rmon2MIBCompliances 1 } + +rmon2MIBApplicationLayerCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "Describes the requirements for conformance to + the RMON2 MIB with Application Layer Enhancements." + MODULE -- this module + MANDATORY-GROUPS { protocolDirectoryGroup, + protocolDistributionGroup, + addressMapGroup, + nlHostGroup, + nlMatrixGroup, + alHostGroup, + alMatrixGroup, + usrHistoryGroup, + probeInformationGroup } + + GROUP rmon1EnhancementGroup + DESCRIPTION + "The rmon1EnhancementGroup is mandatory for systems which + implement RMON [RFC1757]" + ::= { rmon2MIBCompliances 2 } + + +protocolDirectoryGroup OBJECT-GROUP + OBJECTS { protocolDirLastChange, + protocolDirLocalIndex, protocolDirDescr, + protocolDirType, protocolDirAddressMapConfig, + protocolDirHostConfig, protocolDirMatrixConfig, + + + protocolDirOwner, protocolDirStatus } + STATUS current + DESCRIPTION + "Lists the inventory of protocols the probe has the capability + of monitoring and allows the addition, deletion, and + configuration of entries in this list." + ::= { rmon2MIBGroups 1 } + +protocolDistributionGroup OBJECT-GROUP + OBJECTS { protocolDistControlDataSource, + protocolDistControlDroppedFrames, + protocolDistControlCreateTime, + protocolDistControlOwner, protocolDistControlStatus, + protocolDistStatsPkts, protocolDistStatsOctets } + STATUS current + DESCRIPTION + "Collects the relative amounts of octets and packets for the + different protocols detected on a network segment." + ::= { rmon2MIBGroups 2 } + +addressMapGroup OBJECT-GROUP + OBJECTS { addressMapInserts, addressMapDeletes, + addressMapMaxDesiredEntries, + addressMapControlDataSource, + addressMapControlDroppedFrames, + addressMapControlOwner, addressMapControlStatus, + addressMapPhysicalAddress, + addressMapLastChange } + STATUS current + DESCRIPTION + "Lists MAC address to network address bindings discovered by + the probe and what interface they were last seen on." + ::= { rmon2MIBGroups 3 } + +nlHostGroup OBJECT-GROUP + OBJECTS { hlHostControlDataSource, + hlHostControlNlDroppedFrames, hlHostControlNlInserts, + hlHostControlNlDeletes, + hlHostControlNlMaxDesiredEntries, + hlHostControlAlDroppedFrames, hlHostControlAlInserts, + hlHostControlAlDeletes, + hlHostControlAlMaxDesiredEntries, hlHostControlOwner, + hlHostControlStatus, nlHostInPkts, nlHostOutPkts, + nlHostInOctets, nlHostOutOctets, + nlHostOutMacNonUnicastPkts, nlHostCreateTime } + STATUS current + DESCRIPTION + "Counts the amount of traffic sent from and to each network + + + address discovered by the probe. Note that while the + hlHostControlTable also has objects that control an optional + alHostTable, implementation of the alHostTable is not required + to fully implement this group." + ::= { rmon2MIBGroups 4 } + +nlMatrixGroup OBJECT-GROUP + OBJECTS { hlMatrixControlDataSource, + hlMatrixControlNlDroppedFrames, + hlMatrixControlNlInserts, hlMatrixControlNlDeletes, + hlMatrixControlNlMaxDesiredEntries, + hlMatrixControlAlDroppedFrames, + hlMatrixControlAlInserts, hlMatrixControlAlDeletes, + hlMatrixControlAlMaxDesiredEntries, + hlMatrixControlOwner, hlMatrixControlStatus, + nlMatrixSDPkts, nlMatrixSDOctets, nlMatrixSDCreateTime, + nlMatrixDSPkts, nlMatrixDSOctets, nlMatrixDSCreateTime, + nlMatrixTopNControlMatrixIndex, + nlMatrixTopNControlRateBase, + nlMatrixTopNControlTimeRemaining, + nlMatrixTopNControlGeneratedReports, + nlMatrixTopNControlDuration, + nlMatrixTopNControlRequestedSize, + nlMatrixTopNControlGrantedSize, + nlMatrixTopNControlStartTime, + nlMatrixTopNControlOwner, nlMatrixTopNControlStatus, + nlMatrixTopNProtocolDirLocalIndex, + nlMatrixTopNSourceAddress, nlMatrixTopNDestAddress, + nlMatrixTopNPktRate, nlMatrixTopNReversePktRate, + nlMatrixTopNOctetRate, nlMatrixTopNReverseOctetRate } + STATUS current + DESCRIPTION + "Counts the amount of traffic sent between each pair of + network addresses discovered by the probe. Note that while the + hlMatrixControlTable also has objects that control optional + alMatrixTables, implementation of the alMatrixTables is not + required to fully implement this group." + ::= { rmon2MIBGroups 5 } + +alHostGroup OBJECT-GROUP + OBJECTS { alHostInPkts, alHostOutPkts, + alHostInOctets, alHostOutOctets, alHostCreateTime } + STATUS current + DESCRIPTION + "Counts the amount of traffic, by protocol, sent from and to + each network address discovered by the probe. Implementation + of this group requires implementation of the Network Layer + Host Group." + + + ::= { rmon2MIBGroups 6 } + +alMatrixGroup OBJECT-GROUP + OBJECTS { alMatrixSDPkts, alMatrixSDOctets, alMatrixSDCreateTime, + alMatrixDSPkts, alMatrixDSOctets, alMatrixDSCreateTime, + alMatrixTopNControlMatrixIndex, + alMatrixTopNControlRateBase, + alMatrixTopNControlTimeRemaining, + alMatrixTopNControlGeneratedReports, + alMatrixTopNControlDuration, + alMatrixTopNControlRequestedSize, + alMatrixTopNControlGrantedSize, + alMatrixTopNControlStartTime, + alMatrixTopNControlOwner, alMatrixTopNControlStatus, + alMatrixTopNProtocolDirLocalIndex, + alMatrixTopNSourceAddress, alMatrixTopNDestAddress, + alMatrixTopNAppProtocolDirLocalIndex, + alMatrixTopNPktRate, alMatrixTopNReversePktRate, + alMatrixTopNOctetRate, alMatrixTopNReverseOctetRate } + STATUS current + DESCRIPTION + "Counts the amount of traffic, by protocol, sent between each + pair of network addresses discovered by the + probe. Implementation of this group requires implementation of + the Network Layer Matrix Group." + ::= { rmon2MIBGroups 7 } + +usrHistoryGroup OBJECT-GROUP + OBJECTS { usrHistoryControlObjects, + usrHistoryControlBucketsRequested, + usrHistoryControlBucketsGranted, + usrHistoryControlInterval, + usrHistoryControlOwner, usrHistoryControlStatus, + usrHistoryObjectVariable, usrHistoryObjectSampleType, + usrHistoryIntervalStart, usrHistoryIntervalEnd, + usrHistoryAbsValue, usrHistoryValStatus } + STATUS current + DESCRIPTION + "The usrHistoryGroup provides user-defined collection of + historical information from MIB objects on the probe." + ::= { rmon2MIBGroups 8 } + +probeInformationGroup OBJECT-GROUP + OBJECTS { probeCapabilities, + probeSoftwareRev, probeHardwareRev, probeDateTime } + STATUS current + DESCRIPTION + "This group describes various operating parameters of the + + + probe as well as controlling the local time of the probe." + ::= { rmon2MIBGroups 9 } + +probeConfigurationGroup OBJECT-GROUP + OBJECTS { probeResetControl, probeDownloadFile, + probeDownloadTFTPServer, probeDownloadAction, + probeDownloadStatus, + serialMode, serialProtocol, serialTimeout, + serialModemInitString, serialModemHangUpString, + serialModemConnectResp, serialModemNoConnectResp, + serialDialoutTimeout, serialStatus, + netConfigIPAddress, netConfigSubnetMask, + netConfigStatus, netDefaultGateway, + trapDestCommunity, trapDestProtocol, trapDestAddress, + trapDestOwner, trapDestStatus, + serialConnectDestIpAddress, serialConnectType, + serialConnectDialString, serialConnectSwitchConnectSeq, + serialConnectSwitchDisconnectSeq, + serialConnectSwitchResetSeq, + serialConnectOwner, serialConnectStatus } + STATUS current + DESCRIPTION + "This group controls the configuration of various operating + parameters of the probe." + ::= { rmon2MIBGroups 10 } + +rmon1EnhancementGroup OBJECT-GROUP + OBJECTS { historyControlDroppedFrames, hostControlDroppedFrames, + hostControlCreateTime, matrixControlDroppedFrames, + matrixControlCreateTime, channelDroppedFrames, + channelCreateTime, filterProtocolDirDataLocalIndex, + filterProtocolDirLocalIndex } + STATUS current + DESCRIPTION + "This group adds some enhancements to RMON-1 that help + management stations." + ::= { rmon2MIBGroups 11 } + +rmon1EthernetEnhancementGroup OBJECT-GROUP + OBJECTS { etherStatsDroppedFrames, etherStatsCreateTime } + STATUS current + DESCRIPTION + "This group adds some enhancements to RMON-1 that help + management stations." + ::= { rmon2MIBGroups 12 } + +rmon1TokenRingEnhancementGroup OBJECT-GROUP + OBJECTS { tokenRingMLStatsDroppedFrames, + + + tokenRingMLStatsCreateTime, + tokenRingPStatsDroppedFrames, tokenRingPStatsCreateTime, + ringStationControlDroppedFrames, + ringStationControlCreateTime, + sourceRoutingStatsDroppedFrames, + sourceRoutingStatsCreateTime } + STATUS current + DESCRIPTION + "This group adds some enhancements to RMON-1 that help + management stations." + ::= { rmon2MIBGroups 13 } +END + + diff --git a/lib/snmp/test/test-mibs/SNMPv2-MIB.mib b/lib/snmp/test/test-mibs/SNMPv2-MIB.mib new file mode 100644 index 0000000000..0c5418b9ce --- /dev/null +++ b/lib/snmp/test/test-mibs/SNMPv2-MIB.mib @@ -0,0 +1,777 @@ +SNMPv2-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2 + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF; + +snmpMIB MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "IETF SNMPv2 Working Group" + CONTACT-INFO + " Marshall T. Rose + + Postal: Dover Beach Consulting, Inc. + 420 Whisman Court + Mountain View, CA 94043-2186 + US + + Tel: +1 415 968 1052 + + E-mail: [email protected]" + DESCRIPTION + "The MIB module for SNMPv2 entities." + REVISION "9304010000Z" + DESCRIPTION + "The initial revision of this MIB module was published as + RFC 1450." + ::= { snmpModules 1 } + + +snmpMIBObjects OBJECT IDENTIFIER ::= { snmpMIB 1 } + +-- ::= { snmpMIBObjects 1 } this OID is obsolete +-- ::= { snmpMIBObjects 2 } this OID is obsolete +-- ::= { snmpMIBObjects 3 } this OID is obsolete + + +-- the System group +-- +-- a collection of objects common to all managed systems. + +system OBJECT IDENTIFIER ::= { mib-2 1 } + +sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the entity. This value should + include the full name and version identification of the + system's hardware type, software operating-system, and + networking software." + ::= { system 1 } + +sysObjectID OBJECT-TYPE + + + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The vendor's authoritative identification of the network + management subsystem contained in the entity. This value is + allocated within the SMI enterprises subtree (1.3.6.1.4.1) + and provides an easy and unambiguous means for determining + `what kind of box' is being managed. For example, if vendor + `Flintstones, Inc.' was assigned the subtree + 1.3.6.1.4.1.4242, it could assign the identifier + 1.3.6.1.4.1.4242.1.1 to its `Fred Router'." + ::= { system 2 } + +sysUpTime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The time (in hundredths of a second) since the network + management portion of the system was last re-initialized." + ::= { system 3 } + +sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The textual identification of the contact person for this + managed node, together with information on how to contact + this person. If no contact information is known, the value + is the zero-length string." + ::= { system 4 } + +sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An administratively-assigned name for this managed node. + By convention, this is the node's fully-qualified domain + name. If the name is unknown, the value is the zero-length + string." + ::= { system 5 } + +sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The physical location of this node (e.g., `telephone + closet, 3rd floor'). If the location is unknown, the value + is the zero-length string." + ::= { system 6 } + +sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A value which indicates the set of services that this + entity may potentially offers. The value is a sum. This + sum initially takes the value zero, Then, for each layer, L, + in the range 1 through 7, that this node performs + transactions for, 2 raised to (L - 1) is added to the sum. + For example, a node which performs only routing functions + would have a value of 4 (2^(3-1)). In contrast, a node + which is a host offering application services would have a + value of 72 (2^(4-1) + 2^(7-1)). Note that in the context + of the Internet suite of protocols, values should be + calculated accordingly: + + layer functionality + 1 physical (e.g., repeaters) + 2 datalink/subnetwork (e.g., bridges) + 3 internet (e.g., supports the IP) + 4 end-to-end (e.g., supports the TCP) + 7 applications (e.g., supports the SMTP) + + For systems including OSI protocols, layers 5 and 6 may also + be counted." + ::= { system 7 } + + +-- object resource information +-- +-- a collection of objects which describe the SNMPv2 entity's +-- (statically and dynamically configurable) support of +-- various MIB modules. + +sysORLastChange OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time of the most recent + change in state or value of any instance of sysORID." + ::= { system 8 } + +sysORTable OBJECT-TYPE + SYNTAX SEQUENCE OF SysOREntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The (conceptual) table listing the capabilities of the + local SNMPv2 entity acting in an agent role with respect to + various MIB modules. SNMPv2 entities having dynamically- + configurable support of MIB modules will have a + dynamically-varying number of conceptual rows." + ::= { system 9 } + +sysOREntry OBJECT-TYPE + SYNTAX SysOREntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { sysORIndex } + ::= { sysORTable 1 } + +SysOREntry ::= SEQUENCE { + sysORIndex INTEGER, + sysORID OBJECT IDENTIFIER, + sysORDescr DisplayString, + sysORUpTime TimeStamp +} + +sysORIndex OBJECT-TYPE + SYNTAX INTEGER (1..2147483647) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { sysOREntry 1 } + +sysORID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An authoritative identification of a capabilities statement + with respect to various MIB modules supported by the local + SNMPv2 entity acting in an agent role." + + ::= { sysOREntry 2 } + +sysORDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { sysOREntry 3 } + +sysORUpTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time this conceptual row was + last instanciated." + ::= { sysOREntry 4 } + + +-- the SNMP group +-- +-- a collection of objects providing basic instrumentation and +-- control of an SNMP entity. + +snmp OBJECT IDENTIFIER ::= { mib-2 11 } + +snmpInPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of messages delivered to the SNMP entity + from the transport service." + ::= { snmp 1 } + +snmpInBadVersions OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages which were delivered to + the SNMP entity and were for an unsupported SNMP version." + ::= { snmp 3 } + +snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages delivered to the SNMP + entity which used a SNMP community name not known to said + entity." + ::= { snmp 4 } + +snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages delivered to the SNMP + entity which represented an SNMP operation which was not + allowed by the SNMP community named in the message." + ::= { snmp 5 } + +snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of ASN.1 or BER errors encountered by the + SNMP entity when decoding received SNMP messages." + ::= { snmp 6 } + +snmpEnableAuthenTraps OBJECT-TYPE + SYNTAX INTEGER { enabled(1), disabled(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Indicates whether the SNMP entity is permitted to generate + authenticationFailure traps. The value of this object + overrides any configuration information; as such, it + provides a means whereby all authenticationFailure traps may + be disabled. + + Note that it is strongly recommended that this object be + stored in non-volatile memory so that it remains constant + across re-initializations of the network management system." + ::= { snmp 30 } + +snmpSilentDrops OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of GetRequest-PDUs, GetNextRequest-PDUs, + GetBulkRequest-PDUs, SetRequest-PDUs, and InformRequest-PDUs + delivered to the SNMP entity which were silently dropped + because the size of a reply containing an alternate + Response-PDU with an empty variable-bindings field was + greater than either a local constraint or the maximum + message size associated with the originator of the request." + ::= { snmp 31 } + +snmpProxyDrops OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of GetRequest-PDUs, GetNextRequest-PDUs, + GetBulkRequest-PDUs, SetRequest-PDUs, and InformRequest-PDUs + delivered to the SNMP entity which were silently dropped + because the transmission of the (possibly translated) + message to a proxy target failed in a manner (other than a + time-out) such that no Response-PDU could be returned." + ::= { snmp 32 } + + +-- information for notifications +-- +-- a collection of objects which allow the SNMPv2 entity, when +-- acting in an agent role, to be configured to generate +-- SNMPv2-Trap-PDUs. + +snmpTrap OBJECT IDENTIFIER ::= { snmpMIBObjects 4 } + + +snmpTrapOID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS accessible-for-notify + STATUS current + DESCRIPTION + "The authoritative identification of the notification + currently being sent. This variable occurs as the second + varbind in every SNMPv2-Trap-PDU and InformRequest-PDU." + ::= { snmpTrap 1 } + +-- ::= { snmpTrap 2 } this OID is obsolete + +snmpTrapEnterprise OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS accessible-for-notify + STATUS current + DESCRIPTION + "The authoritative identification of the enterprise + associated with the trap currently being sent. When a + SNMPv2 proxy agent is mapping an RFC1157 Trap-PDU into a + SNMPv2-Trap-PDU, this variable occurs as the last varbind." + ::= { snmpTrap 3 } + +-- ::= { snmpTrap 4 } this OID is obsolete + + +-- well-known traps + +snmpTraps OBJECT IDENTIFIER ::= { snmpMIBObjects 5 } + +coldStart NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "A coldStart trap signifies that the SNMPv2 entity, acting + in an agent role, is reinitializing itself and that its + configuration may have been altered." + ::= { snmpTraps 1 } + +tst OBJECT IDENTIFIER ::= { system 0 } + +testTrapv22 NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "This trap is exactly the v2 correspondance of testTrap2 in + TestTrap mib." + ::= { system 0 1 } + + +warmStart NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "A warmStart trap signifies that the SNMPv2 entity, acting + in an agent role, is reinitializing itself such that its + configuration is unaltered." + ::= { snmpTraps 2 } + +-- Note the linkDown NOTIFICATION-TYPE ::= { snmpTraps 3 } +-- and the linkUp NOTIFICATION-TYPE ::= { snmpTraps 4 } +-- are defined in RFC 1573 + +authenticationFailure NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "An authenticationFailure trap signifies that the SNMPv2 + entity, acting in an agent role, has received a protocol + message that is not properly authenticated. While all + implementations of the SNMPv2 must be capable of generating + this trap, the snmpEnableAuthenTraps object indicates + whether this trap will be generated." + ::= { snmpTraps 5 } + +-- Note the egpNeighborLoss NOTIFICATION-TYPE ::= { snmpTraps 6 } +-- is defined in RFC 1213 +-- the set group +-- +-- a collection of objects which allow several cooperating +-- SNMPv2 entities, all acting in a manager role, to +-- coordinate their use of the SNMPv2 set operation. + +snmpSet OBJECT IDENTIFIER ::= { snmpMIBObjects 6 } + + +snmpSetSerialNo OBJECT-TYPE + SYNTAX TestAndIncr + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An advisory lock used to allow several cooperating SNMPv2 + entities, all acting in a manager role, to coordinate their + use of the SNMPv2 set operation. + + This object is used for coarse-grain coordination. To + achieve fine-grain coordination, one or more similar objects + might be defined within each MIB group, as appropriate." + ::= { snmpSet 1 } + + +-- conformance information + +snmpMIBConformance + OBJECT IDENTIFIER ::= { snmpMIB 2 } + +snmpMIBCompliances + OBJECT IDENTIFIER ::= { snmpMIBConformance 1 } +snmpMIBGroups OBJECT IDENTIFIER ::= { snmpMIBConformance 2 } + + +-- compliance statements + +-- ::= { snmpMIBCompliances 1 } this OID is obsolete + +snmpBasicCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for SNMPv2 entities which + implement the SNMPv2 MIB." + MODULE -- this module + MANDATORY-GROUPS { snmpGroup, snmpSetGroup, systemGroup, + snmpBasicNotificationsGroup } + + GROUP snmpCommunityGroup + DESCRIPTION + "This group is mandatory for SNMPv2 entities which + support community-based authentication." + + ::= { snmpMIBCompliances 2 } + + +-- units of conformance + +-- ::= { snmpMIBGroups 1 } this OID is obsolete +-- ::= { snmpMIBGroups 2 } this OID is obsolete +-- ::= { snmpMIBGroups 3 } this OID is obsolete +-- ::= { snmpMIBGroups 4 } this OID is obsolete + +snmpGroup OBJECT-GROUP + OBJECTS { snmpInPkts, + snmpInBadVersions, + snmpInASNParseErrs, + snmpSilentDrops, + snmpProxyDrops, + snmpEnableAuthenTraps } + STATUS current + DESCRIPTION + "A collection of objects providing basic instrumentation and + control of an SNMPv2 entity." + ::= { snmpMIBGroups 8 } + +snmpCommunityGroup OBJECT-GROUP + OBJECTS { snmpInBadCommunityNames, + snmpInBadCommunityUses } + STATUS current + DESCRIPTION + "A collection of objects providing basic instrumentation of + a SNMPv2 entity which supports community-based + authentication." + ::= { snmpMIBGroups 9 } + +snmpSetGroup OBJECT-GROUP + OBJECTS { snmpSetSerialNo } + STATUS current + DESCRIPTION + "A collection of objects which allow several cooperating + SNMPv2 entities, all acting in a manager role, to coordinate + their use of the SNMPv2 set operation." + ::= { snmpMIBGroups 5 } + +systemGroup OBJECT-GROUP + OBJECTS { sysDescr, sysObjectID, sysUpTime, + sysContact, sysName, sysLocation, + sysServices, + sysORLastChange, sysORID, + sysORUpTime, sysORDescr } + STATUS current + DESCRIPTION + "The system group defines objects which are common to all + managed systems." + ::= { snmpMIBGroups 6 } + +snmpBasicNotificationsGroup NOTIFICATION-GROUP + NOTIFICATIONS { coldStart, authenticationFailure } + STATUS current + DESCRIPTION + "The two notifications which an SNMPv2 entity is required to + implement." + ::= { snmpMIBGroups 7 } + + +-- definitions in RFC 1213 made obsolete by the inclusion of a +-- subset of the snmp group in this MIB + +snmpOutPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Messages which were + passed from the SNMP protocol entity to the + transport service." + ::= { snmp 2 } + +-- { snmp 7 } is not used + +snmpInTooBigs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `tooBig'." + ::= { snmp 8 } + +snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `noSuchName'." + ::= { snmp 9 } + +snmpInBadValues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 10 } + +snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number valid SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `readOnly'. It should be noted that it is a + protocol error to generate an SNMP PDU which + contains the value `readOnly' in the error-status + field, as such this object is provided as a means + of detecting incorrect implementations of the + SNMP." + ::= { snmp 11 } + +snmpInGenErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 12 } + +snmpInTotalReqVars OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of MIB objects which have been + retrieved successfully by the SNMP protocol entity + as the result of receiving valid SNMP Get-Request + and Get-Next PDUs." + ::= { snmp 13 } + +snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of MIB objects which have been + altered successfully by the SNMP protocol entity + as the result of receiving valid SNMP Set-Request + PDUs." + ::= { snmp 14 } + +snmpInGetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 15 } + +snmpInGetNexts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 16 } + +snmpInSetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 17 } + +snmpInGetResponses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 18 } + +snmpInTraps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 19 } + +snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `tooBig.'" + ::= { snmp 20 } + +snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status is + `noSuchName'." + ::= { snmp 21 } + +snmpOutBadValues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 22 } + + +-- { snmp 23 } is not used + +snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 24 } + +snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 25 } + +snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 26 } + +snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 27 } + +snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 28 } + +snmpOutTraps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 29 } + +snmpObsoleteGroup OBJECT-GROUP + OBJECTS { snmpOutPkts, snmpInTooBigs, snmpInNoSuchNames, + snmpInBadValues, snmpInReadOnlys, snmpInGenErrs, + snmpInTotalReqVars, snmpInTotalSetVars, + snmpInGetRequests, snmpInGetNexts, snmpInSetRequests, + snmpInGetResponses, snmpInTraps, snmpOutTooBigs, + snmpOutNoSuchNames, snmpOutBadValues, snmpOutGenErrs, + snmpOutGetRequests, snmpOutGetNexts, snmpOutSetRequests, + snmpOutGetResponses, snmpOutTraps } + STATUS obsolete + DESCRIPTION + "A collection of objects from RFC 1213 made obsolete by this + MIB." + ::= { snmpMIBGroups 10 } + +END diff --git a/lib/snmp/test/test-mibs/SNMPv2-TC.mib b/lib/snmp/test/test-mibs/SNMPv2-TC.mib new file mode 100644 index 0000000000..fd6a728ab5 --- /dev/null +++ b/lib/snmp/test/test-mibs/SNMPv2-TC.mib @@ -0,0 +1,799 @@ +SNMPv2-TC DEFINITIONS ::= BEGIN + +snmpMIB MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "ES" + CONTACT-INFO + "eklas@erlang" + DESCRIPTION + "The MIB module for SNMPv2 entities." + ::= { snmpModules 1 } + + +DisplayString ::= TEXTUAL-CONVENTION + DISPLAY-HINT "255a" + STATUS current + DESCRIPTION + "Represents textual information taken from the NVT ASCII + character set, as defined in pages 4, 10-11 of RFC 854. + + To summarize RFC 854, the NVT ASCII repertoire specifies: + + - the use of character codes 0-127 (decimal) + + - the graphics characters (32-126) are interpreted as + US ASCII + + - NUL, LF, CR, BEL, BS, HT, VT and FF have the special + meanings specified in RFC 854 + + - the other 25 codes have no standard interpretation + + - the sequence 'CR LF' means newline + + - the sequence 'CR NUL' means carriage-return + + - an 'LF' not preceded by a 'CR' means moving to the + same column on the next line. + + - the sequence 'CR x' for any x other than LF or NUL is + illegal. (Note that this also means that a string may + end with either 'CR LF' or 'CR NUL', but not with CR.) + + Any object defined using this syntax may not exceed 255 + characters in length." + SYNTAX OCTET STRING (SIZE (0..255)) + + +PhysAddress ::= TEXTUAL-CONVENTION + DISPLAY-HINT "1x:" + STATUS current + DESCRIPTION + "Represents media- or physical-level addresses." + SYNTAX OCTET STRING + + +MacAddress ::= TEXTUAL-CONVENTION + DISPLAY-HINT "1x:" + STATUS current + DESCRIPTION + "Represents an 802 MAC address represented in the + `canonical' order defined by IEEE 802.1a, i.e., as if it + were transmitted least significant bit first, even though + 802.5 (in contrast to other 802.x protocols) requires MAC + addresses to be transmitted most significant bit first." + SYNTAX OCTET STRING (SIZE (6)) + + +TruthValue ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents a boolean value." + SYNTAX INTEGER { true(1), false(2) } + +TestAndIncr ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents integer-valued information used for atomic + operations. When the management protocol is used to specify + that an object instance having this syntax is to be + modified, the new value supplied via the management protocol + must precisely match the value presently held by the + instance. If not, the management protocol set operation + fails with an error of `inconsistentValue'. Otherwise, if + the current value is the maximum value of 2^31-1 (2147483647 + decimal), then the value held by the instance is wrapped to + zero; otherwise, the value held by the instance is + incremented by one. (Note that regardless of whether the + management protocol set operation succeeds, the variable- + binding in the request and response PDUs are identical.) + + The value of the ACCESS clause for objects having this + syntax is either `read-write' or `read-create'. When an + instance of a columnar object having this syntax is created, + any value may be supplied via the management protocol. + + When the network management portion of the system is re- + initialized, the value of every object instance having this + syntax must either be incremented from its value prior to + the re-initialization, or (if the value prior to the re- + initialization is unknown) be set to a pseudo-randomly + generated value." + SYNTAX INTEGER (0..2147483647) + + +AutonomousType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents an independently extensible type identification + value. It may, for example, indicate a particular sub-tree + with further MIB definitions, or define a particular type of + protocol or hardware." + SYNTAX OBJECT IDENTIFIER + + +InstancePointer ::= TEXTUAL-CONVENTION + STATUS obsolete + DESCRIPTION + "A pointer to either a specific instance of a MIB object or + a conceptual row of a MIB table in the managed device. In + the latter case, by convention, it is the name of the + particular instance of the first accessible columnar object + in the conceptual row. + + The two uses of this textual convention are replaced by + VariablePointer and RowPointer, respectively." + SYNTAX OBJECT IDENTIFIER + + +VariablePointer ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "A pointer to a specific object instance. For example, + sysContact.0 or ifInOctets.3." + SYNTAX OBJECT IDENTIFIER + + +RowPointer ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Represents a pointer to a conceptual row. The value is the + name of the instance of the first accessible columnar object + in the conceptual row. + + For example, ifIndex.3 would point to the 3rd row in the + ifTable (note that if ifIndex were not-accessible, then + ifDescr.3 would be used instead)." + SYNTAX OBJECT IDENTIFIER + + +RowStatus ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The RowStatus textual convention is used to manage the + + + + + creation and deletion of conceptual rows, and is used as the + value of the SYNTAX clause for the status column of a + conceptual row (as described in Section 7.7.1 of [2].) + + The status column has six defined values: + + - `active', which indicates that the conceptual row is + available for use by the managed device; + + - `notInService', which indicates that the conceptual + row exists in the agent, but is unavailable for use by + the managed device (see NOTE below); + + - `notReady', which indicates that the conceptual row + exists in the agent, but is missing information + necessary in order to be available for use by the + managed device; + + - `createAndGo', which is supplied by a management + station wishing to create a new instance of a + conceptual row and to have its status automatically set + to active, making it available for use by the managed + device; + + - `createAndWait', which is supplied by a management + station wishing to create a new instance of a + conceptual row (but not make it available for use by + the managed device); and, + + - `destroy', which is supplied by a management station + wishing to delete all of the instances associated with + an existing conceptual row. + + Whereas five of the six values (all except `notReady') may + be specified in a management protocol set operation, only + three values will be returned in response to a management + protocol retrieval operation: `notReady', `notInService' or + `active'. That is, when queried, an existing conceptual row + has only three states: it is either available for use by + the managed device (the status column has value `active'); + it is not available for use by the managed device, though + the agent has sufficient information to make it so (the + status column has value `notInService'); or, it is not + available for use by the managed device, and an attempt to + make it so would fail because the agent has insufficient + information (the state column has value `notReady'). + + + + + + + NOTE WELL + + This textual convention may be used for a MIB table, + irrespective of whether the values of that table's + conceptual rows are able to be modified while it is + active, or whether its conceptual rows must be taken + out of service in order to be modified. That is, it is + the responsibility of the DESCRIPTION clause of the + status column to specify whether the status column must + not be `active' in order for the value of some other + column of the same conceptual row to be modified. If + such a specification is made, affected columns may be + changed by an SNMP set PDU if the RowStatus would not + be equal to `active' either immediately before or after + processing the PDU. In other words, if the PDU also + contained a varbind that would change the RowStatus + value, the column in question may be changed if the + RowStatus was not equal to `active' as the PDU was + received, or if the varbind sets the status to a value + other than 'active'. + + + Also note that whenever any elements of a row exist, the + RowStatus column must also exist. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To summarize the effect of having a conceptual row with a + status column having a SYNTAX clause value of RowStatus, + consider the following state diagram: + + + STATE + +--------------+-----------+-------------+------------- + | A | B | C | D + | |status col.|status column| + |status column | is | is |status column + ACTION |does not exist| notReady | notInService| is active +--------------+--------------+-----------+-------------+------------- +set status |noError ->D|inconsist- |inconsistent-|inconsistent- +column to | or | entValue| Value| Value +createAndGo |inconsistent- | | | + | Value| | | +--------------+--------------+-----------+-------------+------------- +set status |noError see 1|inconsist- |inconsistent-|inconsistent- +column to | or | entValue| Value| Value +createAndWait |wrongValue | | | +--------------+--------------+-----------+-------------+------------- +set status |inconsistent- |inconsist- |noError |noError +column to | Value| entValue| | +active | | | | + | | or | | + | | | | + | |see 2 ->D| ->D| ->D +--------------+--------------+-----------+-------------+------------- +set status |inconsistent- |inconsist- |noError |noError ->C +column to | Value| entValue| | +notInService | | | | + | | or | | or + | | | | + | |see 3 ->C| ->C|wrongValue +--------------+--------------+-----------+-------------+------------- +set status |noError |noError |noError |noError +column to | | | | +destroy | ->A| ->A| ->A| ->A +--------------+--------------+-----------+-------------+------------- +set any other |see 4 |noError |noError |see 5 +column to some| | | | +value | | see 1| ->C| ->D +--------------+--------------+-----------+-------------+------------- + + (1) goto B or C, depending on information available to the + agent. + + + + + + + (2) if other variable bindings included in the same PDU, + provide values for all columns which are missing but + required, then return noError and goto D. + + (3) if other variable bindings included in the same PDU, + provide values for all columns which are missing but + required, then return noError and goto C. + + (4) at the discretion of the agent, the return value may be + either: + + inconsistentName: because the agent does not choose to + create such an instance when the corresponding + RowStatus instance does not exist, or + + inconsistentValue: if the supplied value is + inconsistent with the state of some other MIB object's + value, or + + noError: because the agent chooses to create the + instance. + + If noError is returned, then the instance of the status + column must also be created, and the new state is B or C, + depending on the information available to the agent. If + inconsistentName or inconsistentValue is returned, the row + remains in state A. + + (5) depending on the MIB definition for the column/table, + either noError or inconsistentValue may be returned. + + NOTE: Other processing of the set request may result in a + response other than noError being returned, e.g., + wrongValue, noCreation, etc. + + + Conceptual Row Creation + + There are four potential interactions when creating a + conceptual row: selecting an instance-identifier which is + not in use; creating the conceptual row; initializing any + objects for which the agent does not supply a default; and, + making the conceptual row available for use by the managed + device. + + + + + + + + + Interaction 1: Selecting an Instance-Identifier + + The algorithm used to select an instance-identifier varies + for each conceptual row. In some cases, the instance- + identifier is semantically significant, e.g., the + destination address of a route, and a management station + selects the instance-identifier according to the semantics. + + In other cases, the instance-identifier is used solely to + distinguish conceptual rows, and a management station + without specific knowledge of the conceptual row might + examine the instances present in order to determine an + unused instance-identifier. (This approach may be used, but + it is often highly sub-optimal; however, it is also a + questionable practice for a naive management station to + attempt conceptual row creation.) + + Alternately, the MIB module which defines the conceptual row + might provide one or more objects which provide assistance + in determining an unused instance-identifier. For example, + if the conceptual row is indexed by an integer-value, then + an object having an integer-valued SYNTAX clause might be + defined for such a purpose, allowing a management station to + issue a management protocol retrieval operation. In order + to avoid unnecessary collisions between competing management + stations, `adjacent' retrievals of this object should be + different. + + Finally, the management station could select a pseudo-random + number to use as the index. In the event that this index + was already in use and an inconsistentValue was returned in + response to the management protocol set operation, the + management station should simply select a new pseudo-random + number and retry the operation. + + A MIB designer should choose between the two latter + algorithms based on the size of the table (and therefore the + efficiency of each algorithm). For tables in which a large + number of entries are expected, it is recommended that a MIB + object be defined that returns an acceptable index for + creation. For tables with small numbers of entries, it is + recommended that the latter pseudo-random index mechanism be + used. + + + + + + + + + + Interaction 2: Creating the Conceptual Row + + Once an unused instance-identifier has been selected, the + management station determines if it wishes to create and + activate the conceptual row in one transaction or in a + negotiated set of interactions. + + Interaction 2a: Creating and Activating the Conceptual Row + + The management station must first determine the column + requirements, i.e., it must determine those columns for + which it must or must not provide values. Depending on the + complexity of the table and the management station's + knowledge of the agent's capabilities, this determination + can be made locally by the management station. Alternately, + the management station issues a management protocol get + operation to examine all columns in the conceptual row that + it wishes to create. In response, for each column, there + are three possible outcomes: + + - a value is returned, indicating that some other + management station has already created this conceptual + row. We return to interaction 1. + + - the exception `noSuchInstance' is returned, + indicating that the agent implements the object-type + associated with this column, and that this column in at + least one conceptual row would be accessible in the MIB + view used by the retrieval were it to exist. For those + columns to which the agent provides read-create access, + the `noSuchInstance' exception tells the management + station that it should supply a value for this column + when the conceptual row is to be created. + + - the exception `noSuchObject' is returned, indicating + that the agent does not implement the object-type + associated with this column or that there is no + conceptual row for which this column would be + accessible in the MIB view used by the retrieval. As + such, the management station can not issue any + management protocol set operations to create an + instance of this column. + + Once the column requirements have been determined, a + management protocol set operation is accordingly issued. + This operation also sets the new instance of the status + column to `createAndGo'. + + + + + + When the agent processes the set operation, it verifies that + it has sufficient information to make the conceptual row + available for use by the managed device. The information + available to the agent is provided by two sources: the + management protocol set operation which creates the + conceptual row, and, implementation-specific defaults + supplied by the agent (note that an agent must provide + implementation-specific defaults for at least those objects + which it implements as read-only). If there is sufficient + information available, then the conceptual row is created, a + `noError' response is returned, the status column is set to + `active', and no further interactions are necessary (i.e., + interactions 3 and 4 are skipped). If there is insufficient + information, then the conceptual row is not created, and the + set operation fails with an error of `inconsistentValue'. + On this error, the management station can issue a management + protocol retrieval operation to determine if this was + because it failed to specify a value for a required column, + or, because the selected instance of the status column + already existed. In the latter case, we return to + interaction 1. In the former case, the management station + can re-issue the set operation with the additional + information, or begin interaction 2 again using + `createAndWait' in order to negotiate creation of the + conceptual row. + + NOTE WELL + + Regardless of the method used to determine the column + requirements, it is possible that the management + station might deem a column necessary when, in fact, + the agent will not allow that particular columnar + instance to be created or written. In this case, the + management protocol set operation will fail with an + error such as `noCreation' or `notWritable'. In this + case, the management station decides whether it needs + to be able to set a value for that particular columnar + instance. If not, the management station re-issues the + management protocol set operation, but without setting + a value for that particular columnar instance; + otherwise, the management station aborts the row + creation algorithm. + + Interaction 2b: Negotiating the Creation of the Conceptual + Row + + The management station issues a management protocol set + operation which sets the desired instance of the status + + + + + column to `createAndWait'. If the agent is unwilling to + process a request of this sort, the set operation fails with + an error of `wrongValue'. (As a consequence, such an agent + must be prepared to accept a single management protocol set + operation, i.e., interaction 2a above, containing all of the + columns indicated by its column requirements.) Otherwise, + the conceptual row is created, a `noError' response is + returned, and the status column is immediately set to either + `notInService' or `notReady', depending on whether it has + sufficient information to make the conceptual row available + for use by the managed device. If there is sufficient + information available, then the status column is set to + `notInService'; otherwise, if there is insufficient + information, then the status column is set to `notReady'. + Regardless, we proceed to interaction 3. + + Interaction 3: Initializing non-defaulted Objects + + The management station must now determine the column + requirements. It issues a management protocol get operation + to examine all columns in the created conceptual row. In + the response, for each column, there are three possible + outcomes: + + - a value is returned, indicating that the agent + implements the object-type associated with this column + and had sufficient information to provide a value. For + those columns to which the agent provides read-create + access (and for which the agent allows their values to + be changed after their creation), a value return tells + the management station that it may issue additional + management protocol set operations, if it desires, in + order to change the value associated with this column. + + - the exception `noSuchInstance' is returned, + indicating that the agent implements the object-type + associated with this column, and that this column in at + least one conceptual row would be accessible in the MIB + view used by the retrieval were it to exist. However, + the agent does not have sufficient information to + provide a value, and until a value is provided, the + conceptual row may not be made available for use by the + managed device. For those columns to which the agent + provides read-create access, the `noSuchInstance' + exception tells the management station that it must + issue additional management protocol set operations, in + order to provide a value associated with this column. + + + + + + - the exception `noSuchObject' is returned, indicating + that the agent does not implement the object-type + associated with this column or that there is no + conceptual row for which this column would be + accessible in the MIB view used by the retrieval. As + such, the management station can not issue any + management protocol set operations to create an + instance of this column. + + If the value associated with the status column is + `notReady', then the management station must first deal with + all `noSuchInstance' columns, if any. Having done so, the + value of the status column becomes `notInService', and we + proceed to interaction 4. + + Interaction 4: Making the Conceptual Row Available + + Once the management station is satisfied with the values + associated with the columns of the conceptual row, it issues + a management protocol set operation to set the status column + to `active'. If the agent has sufficient information to + make the conceptual row available for use by the managed + device, the management protocol set operation succeeds (a + `noError' response is returned). Otherwise, the management + protocol set operation fails with an error of + `inconsistentValue'. + + + NOTE WELL + + A conceptual row having a status column with value + `notInService' or `notReady' is unavailable to the + managed device. As such, it is possible for the + managed device to create its own instances during the + time between the management protocol set operation + which sets the status column to `createAndWait' and the + management protocol set operation which sets the status + column to `active'. In this case, when the management + protocol set operation is issued to set the status + column to `active', the values held in the agent + supersede those used by the managed device. + + If the management station is prevented from setting the + status column to `active' (e.g., due to management station + or network failure) the conceptual row will be left in the + `notInService' or `notReady' state, consuming resources + indefinitely. The agent must detect conceptual rows that + have been in either state for an abnormally long period of + + + + + time and remove them. It is the responsibility of the + DESCRIPTION clause of the status column to indicate what an + abnormally long period of time would be. This period of + time should be long enough to allow for human response time + (including `think time') between the creation of the + conceptual row and the setting of the status to `active'. + In the absense of such information in the DESCRIPTION + clause, it is suggested that this period be approximately 5 + minutes in length. This removal action applies not only to + newly-created rows, but also to previously active rows which + are set to, and left in, the notInService state for a + prolonged period exceeding that which is considered normal + for such a conceptual row. + + + Conceptual Row Suspension + + When a conceptual row is `active', the management station + may issue a management protocol set operation which sets the + instance of the status column to `notInService'. If the + agent is unwilling to do so, the set operation fails with an + error of `wrongValue'. Otherwise, the conceptual row is + taken out of service, and a `noError' response is returned. + It is the responsibility of the DESCRIPTION clause of the + status column to indicate under what circumstances the + status column should be taken out of service (e.g., in order + for the value of some other column of the same conceptual + row to be modified). + + + Conceptual Row Deletion + + For deletion of conceptual rows, a management protocol set + operation is issued which sets the instance of the status + column to `destroy'. This request may be made regardless of + the current value of the status column (e.g., it is possible + to delete conceptual rows which are either `notReady', + `notInService' or `active'.) If the operation succeeds, + then all instances associated with the conceptual row are + immediately removed." + + + SYNTAX INTEGER { + -- the following two values are states: + -- these values may be read or written + active(1), + notInService(2), + + + + + + -- the following value is a state: + -- this value may be read, but not written + notReady(3), + + -- the following three values are + -- actions: these values may be written, + -- but are never read + createAndGo(4), + createAndWait(5), + destroy(6) + } + + +TimeStamp ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The value of the sysUpTime object at which a specific + occurrence happened. The specific occurrence must be + defined in the description of any object defined using this + type." + SYNTAX TimeTicks + + +TimeInterval ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "A period of time, measured in units of 0.01 seconds." + SYNTAX INTEGER (0..2147483647) + + +DateAndTime ::= TEXTUAL-CONVENTION + DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d" + STATUS current + DESCRIPTION + "A date-time specification. + + field octets contents range + ----- ------ -------- ----- + 1 1-2 year 0..65536 + 2 3 month 1..12 + 3 4 day 1..31 + 4 5 hour 0..23 + 5 6 minutes 0..59 + 6 7 seconds 0..60 + (use 60 for leap-second) + 7 8 deci-seconds 0..9 + 8 9 direction from UTC '+' / '-' + 9 10 hours from UTC 0..11 + + + + + 10 11 minutes from UTC 0..59 + + For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be + displayed as: + + 1992-5-26,13:30:15.0,-4:0 + + Note that if only local time is known, then timezone + information (fields 8-10) is not present." + SYNTAX OCTET STRING (SIZE (8 | 11)) + + +StorageType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Describes the memory realization of a conceptual row. A + row which is volatile(2) is lost upon reboot. A row which + is either nonVolatile(3), permanent(4) or readOnly(5), is + backed up by stable storage. A row which is permanent(4) + can be changed but not deleted. A row which is readOnly(5) + cannot be changed nor deleted. + + If the value of an object with this syntax is either + permanent(4) or readOnly(5), it cannot be modified. + Conversely, if the value is either other(1), volatile(2) or + nonVolatile(3), it cannot be modified to be permanent(4) or + readOnly(5). + + Every usage of this textual convention is required to + specify the columnar objects which a permanent(4) row must + at a minimum allow to be writable." + SYNTAX INTEGER { + other(1), -- eh? + volatile(2), -- e.g., in RAM + nonVolatile(3), -- e.g., in NVRAM + permanent(4), -- e.g., partially in ROM + readOnly(5) -- e.g., completely in ROM + } + + +TDomain ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Denotes a kind of transport service. + + Some possible values, such as snmpUDPDomain, are defined in + 'Transport Mappings for Version 2 of the Simple Network + Management Protocol (SNMPv2)'." + + + + + SYNTAX OBJECT IDENTIFIER + + +TAddress ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "Denotes a transport service address. + + For snmpUDPDomain, a TAddress is 6 octets long, the initial 4 + octets containing the IP-address in network-byte order and the + last 2 containing the UDP port in network-byte order. Consult + 'Transport Mappings for Version 2 of the Simple Network + Management Protocol (SNMPv2)' for further information on + snmpUDPDomain." + SYNTAX OCTET STRING (SIZE (1..255)) + + +END diff --git a/lib/snmp/test/test-mibs/SNMPv2-USEC-MIB.mib b/lib/snmp/test/test-mibs/SNMPv2-USEC-MIB.mib new file mode 100644 index 0000000000..c6dd7750c2 --- /dev/null +++ b/lib/snmp/test/test-mibs/SNMPv2-USEC-MIB.mib @@ -0,0 +1,251 @@ +SNMPv2-USEC-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Counter32, Unsigned32, + snmpModules + FROM SNMPv2-SMI + TEXTUAL-CONVENTION + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP + FROM SNMPv2-CONF; + + +usecMIB MODULE-IDENTITY + LAST-UPDATED "9601120000Z" + ORGANIZATION "IETF SNMPv2 Working Group" + CONTACT-INFO + " Glenn W. Waters + + Postal: Bell-Northern Research, Ltd. + P.O. Box 3511, Station C + Ottawa, ON, K1Y 4H7 + Canada + + Tel: +1 613 763 3933 + + E-mail: [email protected]" + DESCRIPTION + "The MIB module for SNMPv2 entities implementing the user- + based security model." + ::= { snmpModules 6 } + + +usecMIBObjects OBJECT IDENTIFIER ::= { usecMIB 1 } + + +-- Textual Conventions + +AgentID ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "An agent's administratively-unique identifier. + + The value for this object may not be all zeros or all 'ff'H. + + The initial value for this object may be configured via an + operator console entry or via an algorithmic function. In + the later case, the following guidelines are recommended: + + 1) The first four octets are set to the binary equivalent + of the agent's SNMP network management private + enterprise number as assigned by the Internet Assigned + Numbers Authority (IANA). For example, if Acme + Networks has been assigned { enterprises 696 }, the + first four octets would be assigned '000002b8'H. + + 2) The remaining eight octets are the cookie whose + contents are determined via one or more enterprise- + specific methods. Such methods must be designed so as + to maximize the possibility that the value of this + object will be unique in the agent's administrative + domain. For example, the cookie may be the IP address + of the agent, or the MAC address of one of the + interfaces, with each address suitably padded with + random octets. If multiple methods are defined, then + it is recommended that the cookie be further divided + into one octet that indicates the method being used and + seven octets which are a function of the method." + SYNTAX OCTET STRING (SIZE (12)) + + +-- the USEC Basic group +-- +-- a collection of objects providing basic instrumentation of +-- the SNMPv2 entity implementing the user-based security model + + +usecAgent OBJECT IDENTIFIER ::= { usecMIBObjects 1 } + +agentID OBJECT-TYPE + SYNTAX AgentID + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The agent's administratively-unique identifier." + ::= { usecAgent 1 } + +agentBoots OBJECT-TYPE + SYNTAX Unsigned32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times that the agent has re-initialized + itself since its initial configuration." + ::= { usecAgent 2 } + +agentTime OBJECT-TYPE + SYNTAX Unsigned32 (0..2147483647) + UNITS "seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of seconds since the agent last incremented the + agentBoots object." + ::= { usecAgent 3 } + +agentSize OBJECT-TYPE + SYNTAX INTEGER (484..65507) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum length in octets of an SNMPv2 message which + this agent will accept using any transport mapping." + ::= { usecAgent 4 } + + +-- USEC statistics +-- +-- a collection of objects providing basic instrumentation of +-- the SNMPv2 entity implementing the user-based security model + +usecStats OBJECT IDENTIFIER ::= { usecMIBObjects 2 } + + +usecStatsUnsupportedQoS OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received by the SNMPv2 entity + which were dropped because they requested a quality-of- + service that was unknown to the agent or otherwise + unavailable." + ::= { usecStats 1 } + +usecStatsNotInWindows OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received by the SNMPv2 entity + which were dropped because they appeared outside of the + agent's window." + ::= { usecStats 2 } + + +usecStatsUnknownUserNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received by the SNMPv2 entity + which were dropped because they referenced a user that was + not known to the agent." + ::= { usecStats 3 } + +usecStatsWrongDigestValues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received by the SNMPv2 entity + which were dropped because they didn't contain the expected + digest value." + ::= { usecStats 4 } + +usecStatsUnknownContexts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received by the SNMPv2 entity + which were dropped because they referenced a context that + was not known to the agent." + ::= { usecStats 5 } + +usecStatsBadParameters OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received by the SNMPv2 entity + which were dropped because the <parameters> field was + improperly encoded or had invalid syntax." + ::= { usecStats 6 } + +usecStatsUnauthorizedOperations OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received by the SNMPv2 entity + which were dropped because the PDU type referred to an + operation that is invalid or not authorized." + + ::= { usecStats 7 } + + +-- conformance information + +usecMIBConformance + OBJECT IDENTIFIER ::= { usecMIB 2 } + +usecMIBCompliances + OBJECT IDENTIFIER ::= { usecMIBConformance 1 } +usecMIBGroups OBJECT IDENTIFIER ::= { usecMIBConformance 2 } + + +-- compliance statements + +usecMIBCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for SNMPv2 entities which + implement the SNMPv2 USEC model." + MODULE -- this module + MANDATORY-GROUPS { usecBasicGroup, + usecStatsGroup } + ::= { usecMIBCompliances 1 } + + +-- units of conformance + +usecBasicGroup OBJECT-GROUP + OBJECTS { agentID, + agentBoots, + agentTime, + agentSize } + STATUS current + DESCRIPTION + "A collection of objects providing identification, clocks, + and capabilities of an SNMPv2 entity which implements the + SNMPv2 USEC model." + ::= { usecMIBGroups 1 } + +usecStatsGroup OBJECT-GROUP + OBJECTS { usecStatsUnsupportedQoS, + usecStatsNotInWindows, + usecStatsUnknownUserNames, + usecStatsWrongDigestValues, + usecStatsUnknownContexts, + usecStatsBadParameters, + usecStatsUnauthorizedOperations } + + + STATUS current + DESCRIPTION + "A collection of objects providing basic error statistics of + an SNMPv2 entity which implements the SNMPv2 USEC model." + ::= { usecMIBGroups 2 } + +END diff --git a/lib/snmp/test/test-mibs/SNMPv2-test.mib b/lib/snmp/test/test-mibs/SNMPv2-test.mib new file mode 100644 index 0000000000..b02be09138 --- /dev/null +++ b/lib/snmp/test/test-mibs/SNMPv2-test.mib @@ -0,0 +1,777 @@ +SNMPv2-test DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, + TimeTicks, Counter32, snmpModules, mib-2 + FROM SNMPv2-SMI + DisplayString, TestAndIncr, TimeStamp + FROM SNMPv2-TC + MODULE-COMPLIANCE, OBJECT-GROUP, NOTIFICATION-GROUP + FROM SNMPv2-CONF; + +snmpMIB MODULE-IDENTITY + LAST-UPDATED "9511090000Z" + ORGANIZATION "IETF SNMPv2 Working Group" + CONTACT-INFO + " Marshall T. Rose + + Postal: Dover Beach Consulting, Inc. + 420 Whisman Court + Mountain View, CA 94043-2186 + US + + Tel: +1 415 968 1052 + + E-mail: [email protected]" + DESCRIPTION + "The MIB module for SNMPv2 entities." + REVISION "9304010000Z" + DESCRIPTION + "The initial revision of this MIB module was published as + RFC 1450." + ::= { snmpModules 1 } + + +snmpMIBObjects OBJECT IDENTIFIER ::= { snmpMIB 1 } + +-- ::= { snmpMIBObjects 1 } this OID is obsolete +-- ::= { snmpMIBObjects 2 } this OID is obsolete +-- ::= { snmpMIBObjects 3 } this OID is obsolete + + +-- the System group +-- +-- a collection of objects common to all managed systems. + +system OBJECT IDENTIFIER ::= { mib-2 1 } + +sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the entity. This value should + include the full name and version identification of the + system's hardware type, software operating-system, and + networking software." + ::= { system 1 } + +sysObjectID OBJECT-TYPE + + + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The vendor's authoritative identification of the network + management subsystem contained in the entity. This value is + allocated within the SMI enterprises subtree (1.3.6.1.4.1) + and provides an easy and unambiguous means for determining + `what kind of box' is being managed. For example, if vendor + `Flintstones, Inc.' was assigned the subtree + 1.3.6.1.4.1.4242, it could assign the identifier + 1.3.6.1.4.1.4242.1.1 to its `Fred Router'." + ::= { system 2 } + +sysUpTime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The time (in hundredths of a second) since the network + management portion of the system was last re-initialized." + ::= { system 3 } + +sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The textual identification of the contact person for this + managed node, together with information on how to contact + this person. If no contact information is known, the value + is the zero-length string." + ::= { system 4 } + +sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An administratively-assigned name for this managed node. + By convention, this is the node's fully-qualified domain + name. If the name is unknown, the value is the zero-length + string." + ::= { system 5 } + +sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The physical location of this node (e.g., `telephone + closet, 3rd floor'). If the location is unknown, the value + is the zero-length string." + ::= { system 6 } + +sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A value which indicates the set of services that this + entity may potentially offers. The value is a sum. This + sum initially takes the value zero, Then, for each layer, L, + in the range 1 through 7, that this node performs + transactions for, 2 raised to (L - 1) is added to the sum. + For example, a node which performs only routing functions + would have a value of 4 (2^(3-1)). In contrast, a node + which is a host offering application services would have a + value of 72 (2^(4-1) + 2^(7-1)). Note that in the context + of the Internet suite of protocols, values should be + calculated accordingly: + + layer functionality + 1 physical (e.g., repeaters) + 2 datalink/subnetwork (e.g., bridges) + 3 internet (e.g., supports the IP) + 4 end-to-end (e.g., supports the TCP) + 7 applications (e.g., supports the SMTP) + + For systems including OSI protocols, layers 5 and 6 may also + be counted." + ::= { system 7 } + + +-- object resource information +-- +-- a collection of objects which describe the SNMPv2 entity's +-- (statically and dynamically configurable) support of +-- various MIB modules. + +sysORLastChange OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time of the most recent + change in state or value of any instance of sysORID." + ::= { system 8 } + +sysQ OBJECT-TYPE + SYNTAX BITS {q(0), a(1), b(2), c(3)} + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "The auxiliar the SYNTAX." + DEFVAL { { a, b } } + ::= { system 11 } + + +sysORTable OBJECT-TYPE + SYNTAX SEQUENCE OF SysOREntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The (conceptual) table listing the capabilities of the + local SNMPv2 entity acting in an agent role with respect to + various MIB modules. SNMPv2 entities having dynamically- + configurable support of MIB modules will have a + dynamically-varying number of conceptual rows." + ::= { system 9 } + +sysOREntry OBJECT-TYPE + SYNTAX SysOREntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + INDEX { sysORIndex } + ::= { sysORTable 1 } + +SysOREntry ::= SEQUENCE { + sysORIndex INTEGER, + sysORID OBJECT IDENTIFIER, + sysORDescr DisplayString, + sysORUpTime TimeStamp +} + +sysORIndex OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The auxiliary variable used for identifying instances of + the columnar objects in the sysORTable." + ::= { sysOREntry 1 } + +sysORID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An authoritative identification of a capabilities statement + with respect to various MIB modules supported by the local + SNMPv2 entity acting in an agent role." + + ::= { sysOREntry 2 } + +sysORDescr OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A textual description of the capabilities identified by the + corresponding instance of sysORID." + ::= { sysOREntry 3 } + +sysORUpTime OBJECT-TYPE + SYNTAX TimeStamp + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time this conceptual row was + last instanciated." + ::= { sysOREntry 4 } + + +-- the SNMP group +-- +-- a collection of objects providing basic instrumentation and +-- control of an SNMP entity. + +snmp OBJECT IDENTIFIER ::= { mib-2 11 } + +snmpInPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of messages delivered to the SNMP entity + from the transport service." + ::= { snmp 1 } + +snmpInBadVersions OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages which were delivered to + the SNMP entity and were for an unsupported SNMP version." + ::= { snmp 3 } + +snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages delivered to the SNMP + entity which used a SNMP community name not known to said + entity." + ::= { snmp 4 } + +snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of SNMP messages delivered to the SNMP + entity which represented an SNMP operation which was not + allowed by the SNMP community named in the message." + ::= { snmp 5 } + +snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of ASN.1 or BER errors encountered by the + SNMP entity when decoding received SNMP messages." + ::= { snmp 6 } + +snmpEnableAuthenTraps OBJECT-TYPE + SYNTAX INTEGER { enabled(1), disabled(2) } + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "Indicates whether the SNMP entity is permitted to generate + authenticationFailure traps. The value of this object + overrides any configuration information; as such, it + provides a means whereby all authenticationFailure traps may + be disabled. + + Note that it is strongly recommended that this object be + stored in non-volatile memory so that it remains constant + across re-initializations of the network management system." + ::= { snmp 30 } + +snmpSilentDrops OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of GetRequest-PDUs, GetNextRequest-PDUs, + GetBulkRequest-PDUs, SetRequest-PDUs, and InformRequest-PDUs + delivered to the SNMP entity which were silently dropped + because the size of a reply containing an alternate + Response-PDU with an empty variable-bindings field was + greater than either a local constraint or the maximum + message size associated with the originator of the request." + ::= { snmp 31 } + +snmpProxyDrops OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of GetRequest-PDUs, GetNextRequest-PDUs, + GetBulkRequest-PDUs, SetRequest-PDUs, and InformRequest-PDUs + delivered to the SNMP entity which were silently dropped + because the transmission of the (possibly translated) + message to a proxy target failed in a manner (other than a + time-out) such that no Response-PDU could be returned." + ::= { snmp 32 } + + +-- information for notifications +-- +-- a collection of objects which allow the SNMPv2 entity, when +-- acting in an agent role, to be configured to generate +-- SNMPv2-Trap-PDUs. + +snmpTrap OBJECT IDENTIFIER ::= { snmpMIBObjects 4 } + + +snmpTrapOID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS accessible-for-notify + STATUS current + DESCRIPTION + "The authoritative identification of the notification + currently being sent. This variable occurs as the second + varbind in every SNMPv2-Trap-PDU and InformRequest-PDU." + ::= { snmpTrap 1 } + +-- ::= { snmpTrap 2 } this OID is obsolete + +snmpTrapEnterprise OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS accessible-for-notify + STATUS current + DESCRIPTION + "The authoritative identification of the enterprise + associated with the trap currently being sent. When a + SNMPv2 proxy agent is mapping an RFC1157 Trap-PDU into a + SNMPv2-Trap-PDU, this variable occurs as the last varbind." + ::= { snmpTrap 3 } + +-- ::= { snmpTrap 4 } this OID is obsolete + + +-- well-known traps + +snmpTraps OBJECT IDENTIFIER ::= { snmpMIBObjects 5 } + +coldStart NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "A coldStart trap signifies that the SNMPv2 entity, acting + in an agent role, is reinitializing itself and that its + configuration may have been altered." + ::= { snmpTraps 1 } + +warmStart NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "A warmStart trap signifies that the SNMPv2 entity, acting + in an agent role, is reinitializing itself such that its + configuration is unaltered." + ::= { snmpTraps 2 } + +-- Note the linkDown NOTIFICATION-TYPE ::= { snmpTraps 3 } +-- and the linkUp NOTIFICATION-TYPE ::= { snmpTraps 4 } +-- are defined in RFC 1573 + +authenticationFailure NOTIFICATION-TYPE + STATUS current + DESCRIPTION + "An authenticationFailure trap signifies that the SNMPv2 + entity, acting in an agent role, has received a protocol + message that is not properly authenticated. While all + implementations of the SNMPv2 must be capable of generating + this trap, the snmpEnableAuthenTraps object indicates + whether this trap will be generated." + ::= { snmpTraps 5 } + +-- Note the egpNeighborLoss NOTIFICATION-TYPE ::= { snmpTraps 6 } +-- is defined in RFC 1213 +-- the set group +-- +-- a collection of objects which allow several cooperating +-- SNMPv2 entities, all acting in a manager role, to +-- coordinate their use of the SNMPv2 set operation. + +snmpSet OBJECT IDENTIFIER ::= { snmpMIBObjects 6 } + + +snmpSetSerialNo OBJECT-TYPE + SYNTAX TestAndIncr + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "An advisory lock used to allow several cooperating SNMPv2 + entities, all acting in a manager role, to coordinate their + use of the SNMPv2 set operation. + + This object is used for coarse-grain coordination. To + achieve fine-grain coordination, one or more similar objects + might be defined within each MIB group, as appropriate." + ::= { snmpSet 1 } + + +-- conformance information + +snmpMIBConformance + OBJECT IDENTIFIER ::= { snmpMIB 2 } + +snmpMIBCompliances + OBJECT IDENTIFIER ::= { snmpMIBConformance 1 } +snmpMIBGroups OBJECT IDENTIFIER ::= { snmpMIBConformance 2 } + + +-- compliance statements + +-- ::= { snmpMIBCompliances 1 } this OID is obsolete + +snmpBasicCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for SNMPv2 entities which + implement the SNMPv2 MIB." + MODULE -- this module + MANDATORY-GROUPS { snmpGroup, snmpSetGroup, systemGroup, + snmpBasicNotificationsGroup } + + GROUP snmpCommunityGroup + DESCRIPTION + "This group is mandatory for SNMPv2 entities which + support community-based authentication." + + ::= { snmpMIBCompliances 2 } + + +-- units of conformance + +-- ::= { snmpMIBGroups 1 } this OID is obsolete +-- ::= { snmpMIBGroups 2 } this OID is obsolete +-- ::= { snmpMIBGroups 3 } this OID is obsolete +-- ::= { snmpMIBGroups 4 } this OID is obsolete + +snmpGroup OBJECT-GROUP + OBJECTS { snmpInPkts, + snmpInBadVersions, + snmpInASNParseErrs, + snmpSilentDrops, + snmpProxyDrops, + snmpEnableAuthenTraps } + STATUS current + DESCRIPTION + "A collection of objects providing basic instrumentation and + control of an SNMPv2 entity." + ::= { snmpMIBGroups 8 } + +snmpCommunityGroup OBJECT-GROUP + OBJECTS { snmpInBadCommunityNames, + snmpInBadCommunityUses } + STATUS current + DESCRIPTION + "A collection of objects providing basic instrumentation of + a SNMPv2 entity which supports community-based + authentication." + ::= { snmpMIBGroups 9 } + +snmpSetGroup OBJECT-GROUP + OBJECTS { snmpSetSerialNo } + STATUS current + DESCRIPTION + "A collection of objects which allow several cooperating + SNMPv2 entities, all acting in a manager role, to coordinate + their use of the SNMPv2 set operation." + ::= { snmpMIBGroups 5 } + +systemGroup OBJECT-GROUP + OBJECTS { sysDescr, sysObjectID, sysUpTime, + sysContact, sysName, sysLocation, + sysServices, + sysORLastChange, sysORID, + sysORUpTime, sysORDescr } + STATUS current + DESCRIPTION + "The system group defines objects which are common to all + managed systems." + ::= { snmpMIBGroups 6 } + +snmpBasicNotificationsGroup NOTIFICATION-GROUP + NOTIFICATIONS { coldStart, authenticationFailure } + STATUS current + DESCRIPTION + "The two notifications which an SNMPv2 entity is required to + implement." + ::= { snmpMIBGroups 7 } + + +-- definitions in RFC 1213 made obsolete by the inclusion of a +-- subset of the snmp group in this MIB + +snmpOutPkts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Messages which were + passed from the SNMP protocol entity to the + transport service." + ::= { snmp 2 } + +-- { snmp 7 } is not used + +snmpInTooBigs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `tooBig'." + ::= { snmp 8 } + +snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `noSuchName'." + ::= { snmp 9 } + +snmpInBadValues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 10 } + +snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number valid SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `readOnly'. It should be noted that it is a + protocol error to generate an SNMP PDU which + contains the value `readOnly' in the error-status + field, as such this object is provided as a means + of detecting incorrect implementations of the + SNMP." + ::= { snmp 11 } + +snmpInGenErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 12 } + +snmpInTotalReqVars OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of MIB objects which have been + retrieved successfully by the SNMP protocol entity + as the result of receiving valid SNMP Get-Request + and Get-Next PDUs." + ::= { snmp 13 } + +snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of MIB objects which have been + altered successfully by the SNMP protocol entity + as the result of receiving valid SNMP Set-Request + PDUs." + ::= { snmp 14 } + +snmpInGetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 15 } + +snmpInGetNexts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 16 } + +snmpInSetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 17 } + +snmpInGetResponses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 18 } + +snmpInTraps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 19 } + +snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `tooBig.'" + ::= { snmp 20 } + +snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status is + `noSuchName'." + ::= { snmp 21 } + +snmpOutBadValues OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 22 } + + +-- { snmp 23 } is not used + +snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 24 } + +snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 25 } + +snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 26 } + +snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 27 } + +snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 28 } + +snmpOutTraps OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS obsolete + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 29 } + +snmpObsoleteGroup OBJECT-GROUP + OBJECTS { snmpOutPkts, snmpInTooBigs, snmpInNoSuchNames, + snmpInBadValues, snmpInReadOnlys, snmpInGenErrs, + snmpInTotalReqVars, snmpInTotalSetVars, + snmpInGetRequests, snmpInGetNexts, snmpInSetRequests, + snmpInGetResponses, snmpInTraps, snmpOutTooBigs, + snmpOutNoSuchNames, snmpOutBadValues, snmpOutGenErrs, + snmpOutGetRequests, snmpOutGetNexts, snmpOutSetRequests, + snmpOutGetResponses, snmpOutTraps } + STATUS obsolete + DESCRIPTION + "A collection of objects from RFC 1213 made obsolete by this + MIB." + ::= { snmpMIBGroups 10 } + +END diff --git a/lib/snmp/test/test-mibs/STANDARD-MIB.mib b/lib/snmp/test/test-mibs/STANDARD-MIB.mib new file mode 100644 index 0000000000..3b444ce8aa --- /dev/null +++ b/lib/snmp/test/test-mibs/STANDARD-MIB.mib @@ -0,0 +1,518 @@ +STANDARD-MIB DEFINITIONS ::= BEGIN + + IMPORTS + Counter, TimeTicks, IpAddress + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212 + mgmt, NetworkAddress, IpAddress, Counter, Gauge, + TimeTicks + FROM RFC1155-SMI + DisplayString, mib-2 + FROM RFC1213-MIB + OBJECT-TYPE + FROM RFC-1212; + + + -- Standard Datatypes + + -- Represents a boolean value (from rfc1443) + TruthValue ::= INTEGER { true(1), false(2) } + + -- From SNMPv2 (rfc1443) + RowStatus ::= + INTEGER { + -- the following two values are states: + -- these values may be read or written + active(1), + notInService(2), + + -- the following value is a state: + -- this value may be read, but not written + notReady(3), + + -- the following three values are + -- actions: these values may be written, + -- but are never read + createAndGo(4), + createAndWait(5), + destroy(6) + } + + + system OBJECT IDENTIFIER ::= { mib-2 1 } + snmp OBJECT IDENTIFIER ::= { mib-2 11 } + + + -- the System group + + -- Implementation of the System group is mandatory for all + -- systems. If an agent is not configured to have a value + -- for any of these variables, a string of length 0 is + -- returned. + + sysDescr OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A textual description of the entity. This value + should include the full name and version + identification of the system's hardware type, + software operating-system, and networking + software. It is mandatory that this only contain + printable ASCII characters." + ::= { system 1 } + + sysObjectID OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The vendor's authoritative identification of the + network management subsystem contained in the + entity. This value is allocated within the SMI + enterprises subtree (1.3.6.1.4.1) and provides an + easy and unambiguous means for determining `what + kind of box' is being managed. For example, if + vendor `Flintstones, Inc.' was assigned the + subtree 1.3.6.1.4.1.4242, it could assign the + identifier 1.3.6.1.4.1.4242.1.1 to its `Fred + Router'." + ::= { system 2 } + + sysUpTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The time (in hundredths of a second) since the + network management portion of the system was last + re-initialized." + ::= { system 3 } + + sysContact OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The textual identification of the contact person + for this managed node, together with information + on how to contact this person." + ::= { system 4 } + + sysName OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + + + + + + ACCESS read-write + STATUS mandatory + DESCRIPTION + "An administratively-assigned name for this + managed node. By convention, this is the node's + fully-qualified domain name." + ::= { system 5 } + + sysLocation OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The physical location of this node (e.g., + `telephone closet, 3rd floor')." + ::= { system 6 } + + sysServices OBJECT-TYPE + SYNTAX INTEGER (0..127) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "A value which indicates the set of services that + this entity primarily offers. + + The value is a sum. This sum initially takes the + value zero, Then, for each layer, L, in the range + 1 through 7, that this node performs transactions + for, 2 raised to (L - 1) is added to the sum. For + example, a node which performs primarily routing + functions would have a value of 4 (2^(3-1)). In + contrast, a node which is a host offering + application services would have a value of 72 + (2^(4-1) + 2^(7-1)). Note that in the context of + the Internet suite of protocols, values should be + calculated accordingly: + + layer functionality + 1 physical (e.g., repeaters) + 2 datalink/subnetwork (e.g., bridges) + 3 internet (e.g., IP gateways) + 4 end-to-end (e.g., IP hosts) + 7 applications (e.g., mail relays) + + For systems including OSI protocols, layers 5 and + 6 may also be counted." + ::= { system 7 } + + + -- the SNMP group + + -- Implementation of the SNMP group is mandatory for all + -- systems which support an SNMP protocol entity. Some of + -- the objects defined below will be zero-valued in those + -- SNMP implementations that are optimized to support only + -- those functions specific to either a management agent or + -- a management station. In particular, it should be + -- observed that the objects below refer to an SNMP entity, + -- and there may be several SNMP entities residing on a + -- managed node (e.g., if the node is hosting acting as + -- a management station). + + snmpInPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of Messages delivered to the + SNMP entity from the transport service." + ::= { snmp 1 } + + snmpOutPkts OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + passed from the SNMP protocol entity to the + transport service." + ::= { snmp 2 } + + snmpInBadVersions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages which were + delivered to the SNMP protocol entity and were for + an unsupported SNMP version." + ::= { snmp 3 } + + snmpInBadCommunityNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which used a SNMP + community name not known to said entity." + ::= { snmp 4 } + + snmpInBadCommunityUses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Messages delivered to + the SNMP protocol entity which represented an SNMP + operation which was not allowed by the SNMP + community named in the Message." + ::= { snmp 5 } + + snmpInASNParseErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ASN.1 or BER errors + encountered by the SNMP protocol entity when + decoding received SNMP Messages." + ::= { snmp 6 } + + + + + + -- { snmp 7 } is not used + + snmpInTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `tooBig'." + ::= { snmp 8 } + + snmpInNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `noSuchName'." + ::= { snmp 9 } + + snmpInBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 10 } + + snmpInReadOnlys OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number valid SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `readOnly'. It should be noted that it is a + protocol error to generate an SNMP PDU which + contains the value `readOnly' in the error-status + field, as such this object is provided as a means + of detecting incorrect implementations of the + + + + + + SNMP." + ::= { snmp 11 } + + snmpInGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + delivered to the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 12 } + + snmpInTotalReqVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + retrieved successfully by the SNMP protocol entity + as the result of receiving valid SNMP Get-Request + and Get-Next PDUs." + ::= { snmp 13 } + + snmpInTotalSetVars OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MIB objects which have been + altered successfully by the SNMP protocol entity + as the result of receiving valid SNMP Set-Request + PDUs." + ::= { snmp 14 } + + snmpInGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 15 } + + snmpInGetNexts OBJECT-TYPE + SYNTAX Counter + + + + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 16 } + + snmpInSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 17 } + + snmpInGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been accepted and processed by the SNMP + protocol entity." + ::= { snmp 18 } + + snmpInTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been accepted and processed by the SNMP protocol + entity." + ::= { snmp 19 } + + snmpOutTooBigs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `tooBig.'" + ::= { snmp 20 } + + + + + + snmpOutNoSuchNames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status is + `noSuchName'." + ::= { snmp 21 } + + snmpOutBadValues OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `badValue'." + ::= { snmp 22 } + + -- { snmp 23 } is not used + + snmpOutGenErrs OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP PDUs which were + generated by the SNMP protocol entity and for + which the value of the error-status field is + `genErr'." + ::= { snmp 24 } + + snmpOutGetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 25 } + + snmpOutGetNexts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + + + + DESCRIPTION + "The total number of SNMP Get-Next PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 26 } + + snmpOutSetRequests OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Set-Request PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 27 } + + snmpOutGetResponses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Get-Response PDUs which + have been generated by the SNMP protocol entity." + ::= { snmp 28 } + + snmpOutTraps OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of SNMP Trap PDUs which have + been generated by the SNMP protocol entity." + ::= { snmp 29 } + + snmpEnableAuthenTraps OBJECT-TYPE + SYNTAX INTEGER { enabled(1), disabled(2) } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Indicates whether the SNMP agent process is + permitted to generate authentication-failure + traps. The value of this object overrides any + configuration information; as such, it provides a + means whereby all authentication-failure traps may + be disabled. + + Note that it is strongly recommended that this + object be stored in non-volatile memory so that it + remains constant between re-initializations of the + network management system." + ::= { snmp 30 } + + authenticationFailure TRAP-TYPE + ENTERPRISE snmp + DESCRIPTION + "An authenticationFailure trap signifies that + the sending protocol entity is the addressee + of a protocol message that is not properly + authenticated. While implementations of the + SNMP must be capable of generating this trap, + they must also be capable of suppressing the + emission of such traps via an implementation- + specific mechanism." + ::= 4 + + END + diff --git a/lib/snmp/test/test-mibs/TOKEN-RING-RMON-MIB.mib b/lib/snmp/test/test-mibs/TOKEN-RING-RMON-MIB.mib new file mode 100644 index 0000000000..4ad1d88865 --- /dev/null +++ b/lib/snmp/test/test-mibs/TOKEN-RING-RMON-MIB.mib @@ -0,0 +1,2406 @@ + TOKEN-RING-RMON-MIB DEFINITIONS ::= BEGIN + + IMPORTS + Counter, TimeTicks FROM RFC1155-SMI + OBJECT-TYPE FROM RFC-1212 + OwnerString, EntryStatus, -- Textual Conventions + rmon, statistics, history + FROM RFC1271-MIB; + + + -- All representations of MAC addresses in this MIB + -- Module use, as a textual convention (i.e. this + -- convention does not affect their encoding), the + -- data type: + + MacAddress ::= OCTET STRING (SIZE (6)) -- a 6 octet + -- address in + -- the "canonical" + -- order + -- defined by IEEE 802.1a, i.e., as if it were + -- transmitted least significant bit first, even though + -- 802.5 (in contrast to other 802.x protocols) requires + -- MAC addresses to be transmitted most significant bit + -- first. + + TimeInterval ::= INTEGER + -- A period of time, measured in units of 0.01 seconds. + + -- This MIB module uses the extended OBJECT-TYPE macro as + -- defined in [2]. + + -- Token Ring Remote Network Monitoring MIB + + tokenRing OBJECT IDENTIFIER ::= { rmon 10 } + + + -- The Token Ring Mac-Layer Statistics Group + -- + -- Implementation of this group is optional + + tokenRingMLStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF TokenRingMLStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of Mac-Layer Token Ring statistics + + + entries." + ::= { statistics 2 } + + tokenRingMLStatsEntry OBJECT-TYPE + SYNTAX TokenRingMLStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of Mac-Layer statistics kept for a + particular Token Ring interface." + INDEX { tokenRingMLStatsIndex } + ::= { tokenRingMLStatsTable 1 } + + -- As an example, an instance of the + -- tokenRingMLStatsMacOctets object + -- might be named tokenRingMLStatsMacOctets.1 + + TokenRingMLStatsEntry ::= SEQUENCE { + tokenRingMLStatsIndex INTEGER, + tokenRingMLStatsDataSource OBJECT IDENTIFIER, + tokenRingMLStatsDropEvents Counter, + tokenRingMLStatsMacOctets Counter, + tokenRingMLStatsMacPkts Counter, + tokenRingMLStatsRingPurgeEvents Counter, + tokenRingMLStatsRingPurgePkts Counter, + tokenRingMLStatsBeaconEvents Counter, + tokenRingMLStatsBeaconTime TimeInterval, + tokenRingMLStatsBeaconPkts Counter, + tokenRingMLStatsClaimTokenEvents Counter, + tokenRingMLStatsClaimTokenPkts Counter, + tokenRingMLStatsNAUNChanges Counter, + tokenRingMLStatsLineErrors Counter, + tokenRingMLStatsInternalErrors Counter, + tokenRingMLStatsBurstErrors Counter, + tokenRingMLStatsACErrors Counter, + tokenRingMLStatsAbortErrors Counter, + tokenRingMLStatsLostFrameErrors Counter, + tokenRingMLStatsCongestionErrors Counter, + tokenRingMLStatsFrameCopiedErrors Counter, + tokenRingMLStatsFrequencyErrors Counter, + tokenRingMLStatsTokenErrors Counter, + tokenRingMLStatsSoftErrorReports Counter, + tokenRingMLStatsRingPollEvents Counter, + tokenRingMLStatsOwner OwnerString, + tokenRingMLStatsStatus EntryStatus + } + + + + + tokenRingMLStatsIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies this + tokenRingMLStats entry." + ::= { tokenRingMLStatsEntry 1 } + + tokenRingMLStatsDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the source of the data + that this tokenRingMLStats entry is configured to + analyze. This source can be any tokenRing + interface on this device. In order to identify a + particular interface, this object shall identify + the instance of the ifIndex object, defined in + MIB-II [3], for the desired interface. For + example, if an entry were to receive data from + interface #1, this object would be set to + ifIndex.1. + + The statistics in this group reflect all error + reports on the local network segment attached to + the identified interface. + + This object may not be modified if the associated + tokenRingMLStatsStatus object is equal to + valid(1)." + ::= { tokenRingMLStatsEntry 2 } + + tokenRingMLStatsDropEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of events in which packets were + dropped by the probe due to lack of resources. + Note that this number is not necessarily the + number of packets dropped; it is just the number + of times this condition has been detected. This + value is the same as the corresponding + tokenRingPStatsDropEvents." + ::= { tokenRingMLStatsEntry 3 } + + + + tokenRingMLStatsMacOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets of data in MAC packets + (excluding those that were not good frames) + received on the network (excluding framing bits + but including FCS octets)." + ::= { tokenRingMLStatsEntry 4 } + + tokenRingMLStatsMacPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MAC packets (excluding + packets that were not good frames) received." + ::= { tokenRingMLStatsEntry 5 } + + tokenRingMLStatsRingPurgeEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of times that the ring enters + the ring purge state from normal ring state. The + ring purge state that comes in response to the + claim token or beacon state is not counted." + ::= { tokenRingMLStatsEntry 6 } + + tokenRingMLStatsRingPurgePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ring purge MAC packets + detected by probe." + ::= { tokenRingMLStatsEntry 7 } + + tokenRingMLStatsBeaconEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of times that the ring enters a + beaconing state (beaconFrameStreamingState, + beaconBitStreamingState, + + + beaconSetRecoveryModeState, or + beaconRingSignalLossState) from a non-beaconing + state. Note that a change of the source address + of the beacon packet does not constitute a new + beacon event." + ::= { tokenRingMLStatsEntry 8 } + + tokenRingMLStatsBeaconTime OBJECT-TYPE + SYNTAX TimeInterval + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total amount of time that the ring has been + in the beaconing state." + ::= { tokenRingMLStatsEntry 9 } + + tokenRingMLStatsBeaconPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of beacon MAC packets detected + by the probe." + ::= { tokenRingMLStatsEntry 10 } + + tokenRingMLStatsClaimTokenEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of times that the ring enters + the claim token state from normal ring state or + ring purge state. The claim token state that + comes in response to a beacon state is not + counted." + ::= { tokenRingMLStatsEntry 11 } + + tokenRingMLStatsClaimTokenPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of claim token MAC packets + detected by the probe." + ::= { tokenRingMLStatsEntry 12 } + + + + + + tokenRingMLStatsNAUNChanges OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of NAUN changes detected by the + probe." + ::= { tokenRingMLStatsEntry 13 } + + tokenRingMLStatsLineErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of line errors reported in error + reporting packets detected by the probe." + ::= { tokenRingMLStatsEntry 14 } + + tokenRingMLStatsInternalErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of adapter internal errors + reported in error reporting packets detected by + the probe." + ::= { tokenRingMLStatsEntry 15 } + + tokenRingMLStatsBurstErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of burst errors reported in + error reporting packets detected by the probe." + ::= { tokenRingMLStatsEntry 16 } + + tokenRingMLStatsACErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of AC (Address Copied) errors + reported in error reporting packets detected by + the probe." + ::= { tokenRingMLStatsEntry 17 } + + + + + tokenRingMLStatsAbortErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of abort delimiters reported in + error reporting packets detected by the probe." + ::= { tokenRingMLStatsEntry 18 } + + tokenRingMLStatsLostFrameErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of lost frame errors reported in + error reporting packets detected by the probe." + ::= { tokenRingMLStatsEntry 19 } + + tokenRingMLStatsCongestionErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of receive congestion errors + reported in error reporting packets detected by + the probe." + ::= { tokenRingMLStatsEntry 20 } + + tokenRingMLStatsFrameCopiedErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frame copied errors reported + in error reporting packets detected by the probe." + ::= { tokenRingMLStatsEntry 21 } + + tokenRingMLStatsFrequencyErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frequency errors reported in + error reporting packets detected by the probe." + ::= { tokenRingMLStatsEntry 22 } + + + + + + tokenRingMLStatsTokenErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of token errors reported in + error reporting packets detected by the probe." + ::= { tokenRingMLStatsEntry 23 } + + tokenRingMLStatsSoftErrorReports OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of soft error report frames + detected by the probe." + ::= { tokenRingMLStatsEntry 24 } + + tokenRingMLStatsRingPollEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ring poll events detected by + the probe (i.e. the number of ring polls initiated + by the active monitor that were detected)." + ::= { tokenRingMLStatsEntry 25 } + + tokenRingMLStatsOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { tokenRingMLStatsEntry 26 } + + tokenRingMLStatsStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this tokenRingMLStats entry." + ::= { tokenRingMLStatsEntry 27 } + + + + + + + -- The Token Ring Promiscuous Statistics Group + -- + -- Implementation of this group is optional + + tokenRingPStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF TokenRingPStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of promiscuous Token Ring statistics + entries." + ::= { statistics 3 } + + tokenRingPStatsEntry OBJECT-TYPE + SYNTAX TokenRingPStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of promiscuous statistics kept for + non-MAC packets on a particular Token Ring + interface." + INDEX { tokenRingPStatsIndex } + ::= { tokenRingPStatsTable 1 } + + -- As an example, an instance of the + -- tokenRingPStatsDataOctets object + -- might be named tokenRingPStatsDataOctets.1 + + TokenRingPStatsEntry ::= SEQUENCE { + tokenRingPStatsIndex INTEGER, + tokenRingPStatsDataSource OBJECT IDENTIFIER, + tokenRingPStatsDropEvents Counter, + tokenRingPStatsDataOctets Counter, + tokenRingPStatsDataPkts Counter, + tokenRingPStatsDataBroadcastPkts Counter, + tokenRingPStatsDataMulticastPkts Counter, + tokenRingPStatsDataPkts18to63Octets Counter, + tokenRingPStatsDataPkts64to127Octets Counter, + tokenRingPStatsDataPkts128to255Octets Counter, + tokenRingPStatsDataPkts256to511Octets Counter, + tokenRingPStatsDataPkts512to1023Octets Counter, + tokenRingPStatsDataPkts1024to2047Octets Counter, + tokenRingPStatsDataPkts2048to4095Octets Counter, + tokenRingPStatsDataPkts4096to8191Octets Counter, + tokenRingPStatsDataPkts8192to18000Octets Counter, + tokenRingPStatsDataPktsGreaterThan18000Octets Counter, + tokenRingPStatsOwner OwnerString, + tokenRingPStatsStatus EntryStatus + + + } + + tokenRingPStatsIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies this + tokenRingPStats entry." + ::= { tokenRingPStatsEntry 1 } + + tokenRingPStatsDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + ACCESS read-write + STATUS mandatory + DESCRIPTION + "This object identifies the source of the data + that this tokenRingPStats entry is configured to + analyze. This source can be any tokenRing + interface on this device. In order to identify a + particular interface, this object shall identify + the instance of the ifIndex object, defined in + MIB-II [3], for the desired interface. For + example, if an entry were to receive data from + interface #1, this object would be set to + ifIndex.1. + + The statistics in this group reflect all non-MAC + packets on the local network segment attached to + the identified interface. + + This object may not be modified if the associated + tokenRingPStatsStatus object is equal to + valid(1)." + ::= { tokenRingPStatsEntry 2 } + + tokenRingPStatsDropEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of events in which packets were + dropped by the probe due to lack of resources. + Note that this number is not necessarily the + number of packets dropped; it is just the number + of times this condition has been detected. This + value is the same as the corresponding + tokenRingMLStatsDropEvents" + + + ::= { tokenRingPStatsEntry 3 } + + tokenRingPStatsDataOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets of data in good frames + received on the network (excluding framing bits + but including FCS octets) in non-MAC packets." + ::= { tokenRingPStatsEntry 4 } + + tokenRingPStatsDataPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of non-MAC packets in good + frames. received." + ::= { tokenRingPStatsEntry 5 } + + tokenRingPStatsDataBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were directed to an LLC broadcast address + (0xFFFFFFFFFFFF or 0xC000FFFFFFFF)." + ::= { tokenRingPStatsEntry 6 } + + tokenRingPStatsDataMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were directed to a local or global multicast + or functional address. Note that this number does + not include packets directed to the broadcast + address." + ::= { tokenRingPStatsEntry 7 } + + tokenRingPStatsDataPkts18to63Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + + + "The total number of good non-MAC frames received + that were between 18 and 63 octets in length + inclusive, excluding framing bits but including + FCS octets." + ::= { tokenRingPStatsEntry 8 } + + tokenRingPStatsDataPkts64to127Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were between 64 and 127 octets in length + inclusive, excluding framing bits but including + FCS octets." + ::= { tokenRingPStatsEntry 9 } + + tokenRingPStatsDataPkts128to255Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were between 128 and 255 octets in length + inclusive, excluding framing bits but including + FCS octets." + ::= { tokenRingPStatsEntry 10 } + + tokenRingPStatsDataPkts256to511Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were between 256 and 511 octets in length + inclusive, excluding framing bits but including + FCS octets." + ::= { tokenRingPStatsEntry 11 } + + tokenRingPStatsDataPkts512to1023Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were between 512 and 1023 octets in length + inclusive, excluding framing bits but including + FCS octets." + + + ::= { tokenRingPStatsEntry 12 } + + tokenRingPStatsDataPkts1024to2047Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were between 1024 and 2047 octets in length + inclusive, excluding framing bits but including + FCS octets." + ::= { tokenRingPStatsEntry 13 } + + tokenRingPStatsDataPkts2048to4095Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were between 2048 and 4095 octets in length + inclusive, excluding framing bits but including + FCS octets." + ::= { tokenRingPStatsEntry 14 } + + tokenRingPStatsDataPkts4096to8191Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were between 4096 and 8191 octets in length + inclusive, excluding framing bits but including + FCS octets." + ::= { tokenRingPStatsEntry 15 } + + tokenRingPStatsDataPkts8192to18000Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were between 8192 and 18000 octets in length + inclusive, excluding framing bits but including + FCS octets." + ::= { tokenRingPStatsEntry 16 } + + tokenRingPStatsDataPktsGreaterThan18000Octets OBJECT-TYPE + SYNTAX Counter + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + that were greater than 18000 octets in length, + excluding framing bits but including FCS octets." + ::= { tokenRingPStatsEntry 17 } + + tokenRingPStatsOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { tokenRingPStatsEntry 18 } + + tokenRingPStatsStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this tokenRingPStats entry." + ::= { tokenRingPStatsEntry 19 } + + + -- The Token Ring History Groups + + -- When an entry in the historyControlTable is created that + -- identifies a token ring interface as its + -- historyControlDataSource, the probe shall create + -- corresponding entries in the tokenRingMLHistoryTable + -- and/or the tokenRingPHistoryTable, depending on which + -- groups it supports. + + + -- The Token Ring Mac-Layer History Group + -- + -- Implementation of this group is optional. + -- Implementation of this group requires implementation of + -- the historyControl group from RFC1271. + + tokenRingMLHistoryTable OBJECT-TYPE + SYNTAX SEQUENCE OF TokenRingMLHistoryEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of Mac-Layer Token Ring statistics + + + entries." + ::= { history 3 } + + tokenRingMLHistoryEntry OBJECT-TYPE + SYNTAX TokenRingMLHistoryEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of Mac-Layer statistics kept for a + particular Token Ring interface." + INDEX { tokenRingMLHistoryIndex, + tokenRingMLHistorySampleIndex } + ::= { tokenRingMLHistoryTable 1 } + + -- As an example, an instance of the + -- tokenRingMLHistoryMacOctets + -- object might be named tokenRingMLHistoryMacOctets.1.27 + + TokenRingMLHistoryEntry ::= SEQUENCE { + tokenRingMLHistoryIndex INTEGER, + tokenRingMLHistorySampleIndex INTEGER, + tokenRingMLHistoryIntervalStart TimeTicks, + tokenRingMLHistoryDropEvents Counter, + tokenRingMLHistoryMacOctets Counter, + tokenRingMLHistoryMacPkts Counter, + tokenRingMLHistoryRingPurgeEvents Counter, + tokenRingMLHistoryRingPurgePkts Counter, + tokenRingMLHistoryBeaconEvents Counter, + tokenRingMLHistoryBeaconTime TimeInterval, + tokenRingMLHistoryBeaconPkts Counter, + tokenRingMLHistoryClaimTokenEvents Counter, + tokenRingMLHistoryClaimTokenPkts Counter, + tokenRingMLHistoryNAUNChanges Counter, + tokenRingMLHistoryLineErrors Counter, + tokenRingMLHistoryInternalErrors Counter, + tokenRingMLHistoryBurstErrors Counter, + tokenRingMLHistoryACErrors Counter, + tokenRingMLHistoryAbortErrors Counter, + tokenRingMLHistoryLostFrameErrors Counter, + tokenRingMLHistoryCongestionErrors Counter, + tokenRingMLHistoryFrameCopiedErrors Counter, + tokenRingMLHistoryFrequencyErrors Counter, + tokenRingMLHistoryTokenErrors Counter, + tokenRingMLHistorySoftErrorReports Counter, + tokenRingMLHistoryRingPollEvents Counter, + tokenRingMLHistoryActiveStations INTEGER + } + + + + tokenRingMLHistoryIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The history of which this entry is a part. The + history identified by a particular value of this + index is the same history as identified by the + same value of historyControlIndex." + ::= { tokenRingMLHistoryEntry 1 } + + tokenRingMLHistorySampleIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies the particular + Mac-Layer sample this entry represents among all + Mac-Layer samples associated with the same + historyControlEntry. This index starts at 1 and + increases by one as each new sample is taken." + ::= { tokenRingMLHistoryEntry 2 } + + tokenRingMLHistoryIntervalStart OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the start of the + interval over which this sample was measured. If + the probe keeps track of the time of day, it + should start the first sample of the history at a + time such that when the next hour of the day + begins, a sample is started at that instant. Note + that following this rule may require the probe to + delay collecting the first sample of the history, + as each sample must be of the same interval. Also + note that the sample which is currently being + collected is not accessible in this table until + the end of its interval." + ::= { tokenRingMLHistoryEntry 3 } + + tokenRingMLHistoryDropEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of events in which packets were + + + dropped by the probe due to lack of resources + during this sampling interval. Note that this + number is not necessarily the number of packets + dropped, it is just the number of times this + condition has been detected." + ::= { tokenRingMLHistoryEntry 4 } + + tokenRingMLHistoryMacOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets of data in MAC packets + (excluding those that were not good frames) + received on the network during this sampling + interval (excluding framing bits but including FCS + octets)." + ::= { tokenRingMLHistoryEntry 5 } + + tokenRingMLHistoryMacPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of MAC packets (excluding those + that were not good frames) received during this + sampling interval." + ::= { tokenRingMLHistoryEntry 6 } + + tokenRingMLHistoryRingPurgeEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of times that the ring entered + the ring purge state from normal ring state during + this sampling interval. The ring purge state that + comes from the claim token or beacon state is not + counted." + ::= { tokenRingMLHistoryEntry 7 } + + tokenRingMLHistoryRingPurgePkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of Ring Purge MAC packets + detected by the probe during this sampling + + + interval." + ::= { tokenRingMLHistoryEntry 8 } + + tokenRingMLHistoryBeaconEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of times that the ring enters a + beaconing state (beaconFrameStreamingState, + beaconBitStreamingState, + beaconSetRecoveryModeState, or + beaconRingSignalLossState) during this sampling + interval. Note that a change of the source + address of the beacon packet does not constitute a + new beacon event." + ::= { tokenRingMLHistoryEntry 9 } + + tokenRingMLHistoryBeaconTime OBJECT-TYPE + SYNTAX TimeInterval + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The amount of time that the ring has been in the + beaconing state during this sampling interval." + ::= { tokenRingMLHistoryEntry 10 } + + tokenRingMLHistoryBeaconPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of beacon MAC packets detected + by the probe during this sampling interval." + ::= { tokenRingMLHistoryEntry 11 } + + tokenRingMLHistoryClaimTokenEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of times that the ring enters + the claim token state from normal ring state or + ring purge state during this sampling interval. + The claim token state that comes from the beacon + state is not counted." + ::= { tokenRingMLHistoryEntry 12 } + + + + tokenRingMLHistoryClaimTokenPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of claim token MAC packets + detected by the probe during this sampling + interval." + ::= { tokenRingMLHistoryEntry 13 } + + tokenRingMLHistoryNAUNChanges OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of NAUN changes detected by the + probe during this sampling interval." + ::= { tokenRingMLHistoryEntry 14 } + + tokenRingMLHistoryLineErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of line errors reported in error + reporting packets detected by the probe during + this sampling interval." + ::= { tokenRingMLHistoryEntry 15 } + + tokenRingMLHistoryInternalErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of adapter internal errors + reported in error reporting packets detected by + the probe during this sampling interval." + ::= { tokenRingMLHistoryEntry 16 } + + tokenRingMLHistoryBurstErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of burst errors reported in + error reporting packets detected by the probe + during this sampling interval." + ::= { tokenRingMLHistoryEntry 17 } + + + tokenRingMLHistoryACErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of AC (Address Copied) errors + reported in error reporting packets detected by + the probe during this sampling interval." + ::= { tokenRingMLHistoryEntry 18 } + + tokenRingMLHistoryAbortErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of abort delimiters reported in + error reporting packets detected by the probe + during this sampling interval." + ::= { tokenRingMLHistoryEntry 19 } + + tokenRingMLHistoryLostFrameErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of lost frame errors reported in + error reporting packets detected by the probe + during this sampling interval." + ::= { tokenRingMLHistoryEntry 20 } + + tokenRingMLHistoryCongestionErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of receive congestion errors + reported in error reporting packets detected by + the probe during this sampling interval." + ::= { tokenRingMLHistoryEntry 21 } + + tokenRingMLHistoryFrameCopiedErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frame copied errors reported + in error reporting packets detected by the probe + during this sampling interval." + + + ::= { tokenRingMLHistoryEntry 22 } + + tokenRingMLHistoryFrequencyErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frequency errors reported in + error reporting packets detected by the probe + during this sampling interval." + ::= { tokenRingMLHistoryEntry 23 } + + tokenRingMLHistoryTokenErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of token errors reported in + error reporting packets detected by the probe + during this sampling interval." + ::= { tokenRingMLHistoryEntry 24 } + + tokenRingMLHistorySoftErrorReports OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of soft error report frames + detected by the probe during this sampling + interval." + ::= { tokenRingMLHistoryEntry 25 } + + tokenRingMLHistoryRingPollEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of ring poll events detected by + the probe during this sampling interval." + ::= { tokenRingMLHistoryEntry 26 } + + tokenRingMLHistoryActiveStations OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The maximum number of active stations on the ring + detected by the probe during this sampling + + + interval." + ::= { tokenRingMLHistoryEntry 27} + + + -- The Token Ring Promiscuous History Group + -- + -- Implementation of this group is optional. + -- Implementation of this group requires the implementation + -- of the historyControl group from RFC1271. + + tokenRingPHistoryTable OBJECT-TYPE + SYNTAX SEQUENCE OF TokenRingPHistoryEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of promiscuous Token Ring statistics + entries." + ::= { history 4 } + + tokenRingPHistoryEntry OBJECT-TYPE + SYNTAX TokenRingPHistoryEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of promiscuous statistics kept for a + particular Token Ring interface." + INDEX { tokenRingPHistoryIndex, + tokenRingPHistorySampleIndex } + ::= { tokenRingPHistoryTable 1 } + + -- As an example, an instance of the + -- tokenRingPHistoryDataPkts object + -- might be named tokenRingPHistoryDataPkts.1.27 + + TokenRingPHistoryEntry ::= SEQUENCE { + tokenRingPHistoryIndex INTEGER, + tokenRingPHistorySampleIndex INTEGER, + tokenRingPHistoryIntervalStart TimeTicks, + tokenRingPHistoryDropEvents Counter, + tokenRingPHistoryDataOctets Counter, + tokenRingPHistoryDataPkts Counter, + tokenRingPHistoryDataBroadcastPkts Counter, + tokenRingPHistoryDataMulticastPkts Counter, + tokenRingPHistoryDataPkts18to63Octets Counter, + tokenRingPHistoryDataPkts64to127Octets Counter, + tokenRingPHistoryDataPkts128to255Octets Counter, + tokenRingPHistoryDataPkts256to511Octets Counter, + tokenRingPHistoryDataPkts512to1023Octets Counter, + + + tokenRingPHistoryDataPkts1024to2047Octets Counter, + tokenRingPHistoryDataPkts2048to4095Octets Counter, + tokenRingPHistoryDataPkts4096to8191Octets Counter, + tokenRingPHistoryDataPkts8192to18000Octets Counter, + tokenRingPHistoryDataPktsGreaterThan18000Octets Counter + } + + tokenRingPHistoryIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The history of which this entry is a part. The + history identified by a particular value of this + index is the same history as identified by the + same value of historyControlIndex." + ::= { tokenRingPHistoryEntry 1 } + + tokenRingPHistorySampleIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "An index that uniquely identifies the particular + sample this entry represents among all samples + associated with the same historyControlEntry. + This index starts at 1 and increases by one as + each new sample is taken." + ::= { tokenRingPHistoryEntry 2 } + + tokenRingPHistoryIntervalStart OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the start of the + interval over which this sample was measured. If + the probe keeps track of the time of day, it + should start the first sample of the history at a + time such that when the next hour of the day + begins, a sample is started at that instant. Note + that following this rule may require the probe to + delay collecting the first sample of the history, + as each sample must be of the same interval. Also + note that the sample which is currently being + collected is not accessible in this table until + the end of its interval." + ::= { tokenRingPHistoryEntry 3 } + + + tokenRingPHistoryDropEvents OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of events in which packets were + dropped by the probe due to lack of resources + during this sampling interval. Note that this + number is not necessarily the number of packets + dropped, it is just the number of times this + condition has been detected." + ::= { tokenRingPHistoryEntry 4 } + + tokenRingPHistoryDataOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets of data in good frames + received on the network (excluding framing bits + but including FCS octets) in non-MAC packets + during this sampling interval." + ::= { tokenRingPHistoryEntry 5 } + + tokenRingPHistoryDataPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval." + ::= { tokenRingPHistoryEntry 6 } + + tokenRingPHistoryDataBroadcastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were directed + to an LLC broadcast address (0xFFFFFFFFFFFF or + 0xC000FFFFFFFF)." + ::= { tokenRingPHistoryEntry 7 } + + tokenRingPHistoryDataMulticastPkts OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were directed + to a local or global multicast or functional + address. Note that this number does not include + packets directed to the broadcast address." + ::= { tokenRingPHistoryEntry 8 } + + tokenRingPHistoryDataPkts18to63Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were between 18 + and 63 octets in length inclusive, excluding + framing bits but including FCS octets." + ::= { tokenRingPHistoryEntry 9 } + + tokenRingPHistoryDataPkts64to127Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were between 64 + and 127 octets in length inclusive, excluding + framing bits but including FCS octets." + ::= { tokenRingPHistoryEntry 10 } + + tokenRingPHistoryDataPkts128to255Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were between + 128 and 255 octets in length inclusive, excluding + framing bits but including FCS octets." + ::= { tokenRingPHistoryEntry 11 } + + tokenRingPHistoryDataPkts256to511Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were between + + + 256 and 511 octets in length inclusive, excluding + framing bits but including FCS octets." + ::= { tokenRingPHistoryEntry 12 } + + tokenRingPHistoryDataPkts512to1023Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were between + 512 and 1023 octets in length inclusive, excluding + framing bits but including FCS octets." + ::= { tokenRingPHistoryEntry 13 } + + tokenRingPHistoryDataPkts1024to2047Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were between + 1024 and 2047 octets in length inclusive, + excluding framing bits but including FCS octets." + ::= { tokenRingPHistoryEntry 14 } + + tokenRingPHistoryDataPkts2048to4095Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were between + 2048 and 4095 octets in length inclusive, + excluding framing bits but including FCS octets." + ::= { tokenRingPHistoryEntry 15 } + + tokenRingPHistoryDataPkts4096to8191Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were between + 4096 and 8191 octets in length inclusive, + excluding framing bits but including FCS octets." + ::= { tokenRingPHistoryEntry 16 } + + + + tokenRingPHistoryDataPkts8192to18000Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were between + 8192 and 18000 octets in length inclusive, + excluding framing bits but including FCS octets." + ::= { tokenRingPHistoryEntry 17 } + + tokenRingPHistoryDataPktsGreaterThan18000Octets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good non-MAC frames received + during this sampling interval that were greater + than 18000 octets in length, excluding framing + bits but including FCS octets." + ::= { tokenRingPHistoryEntry 18 } + + + -- The Token Ring Ring Station Group + -- + -- Implementation of this group is optional + -- + -- Although the ringStationTable stores entries only for + -- those stations physically attached to the local ring and + -- the number of stations attached to a ring is limited, a + -- probe may still need to free resources when resources + -- grow tight. In such a situation, it is suggested that + -- the probe free only inactive stations, and to + -- first free the stations that have been inactive for the + -- longest time. + + ringStationControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF RingStationControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of ringStation table control entries." + ::= { tokenRing 1 } + + ringStationControlEntry OBJECT-TYPE + SYNTAX RingStationControlEntry + ACCESS not-accessible + STATUS mandatory + + + DESCRIPTION + "A list of parameters that set up the discovery of + stations on a particular interface and the + collection of statistics about these stations." + INDEX { ringStationControlIfIndex } + ::= { ringStationControlTable 1 } + + -- As an example, an instance of the + -- ringStationControlIfIndex object + -- might be named ringStationControlIfIndex.1 + + RingStationControlEntry ::= SEQUENCE { + ringStationControlIfIndex INTEGER, + ringStationControlTableSize INTEGER, + ringStationControlActiveStations INTEGER, + ringStationControlRingState INTEGER, + ringStationControlBeaconSender MacAddress, + ringStationControlBeaconNAUN MacAddress, + ringStationControlActiveMonitor MacAddress, + ringStationControlOrderChanges Counter, + ringStationControlOwner OwnerString, + ringStationControlStatus EntryStatus + } + + ringStationControlIfIndex OBJECT-TYPE + SYNTAX INTEGER (1..65535) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies the + interface on this remote network monitoring device + from which ringStation data is collected. The + interface identified by a particular value of this + object is the same interface as identified by the + same value of the ifIndex object, defined in MIB- + II [3]." + ::= { ringStationControlEntry 1 } + + ringStationControlTableSize OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of ringStationEntries in the + ringStationTable associated with this + ringStationControlEntry." + ::= { ringStationControlEntry 2 } + + + + ringStationControlActiveStations OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of active ringStationEntries in the + ringStationTable associated with this + ringStationControlEntry." + ::= { ringStationControlEntry 3 } + + ringStationControlRingState OBJECT-TYPE + SYNTAX INTEGER { + normalOperation(1), + ringPurgeState(2), + claimTokenState(3), + beaconFrameStreamingState(4), + beaconBitStreamingState(5), + beaconRingSignalLossState(6), + beaconSetRecoveryModeState(7) + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The current status of this ring." + ::= { ringStationControlEntry 4 } + + ringStationControlBeaconSender OBJECT-TYPE + SYNTAX MacAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The address of the sender of the last beacon + frame received by the probe on this ring. If no + beacon frames have been received, this object + shall be equal to six octets of zero." + ::= { ringStationControlEntry 5 } + + ringStationControlBeaconNAUN OBJECT-TYPE + SYNTAX MacAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The address of the NAUN in the last beacon frame + received by the probe on this ring. If no beacon + frames have been received, this object shall be + equal to six octets of zero." + ::= { ringStationControlEntry 6 } + + + + ringStationControlActiveMonitor OBJECT-TYPE + SYNTAX MacAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The address of the Active Monitor on this + segment. If this address is unknown, this object + shall be equal to six octets of zero." + ::= { ringStationControlEntry 7 } + + ringStationControlOrderChanges OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of add and delete events in the + ringStationOrderTable optionally associated with + this ringStationControlEntry." + ::= { ringStationControlEntry 8 } + + ringStationControlOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { ringStationControlEntry 9 } + + ringStationControlStatus OBJECT-TYPE + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this ringStationControl entry. + + If this object is not equal to valid(1), all + associated entries in the ringStationTable shall + be deleted by the agent." + ::= { ringStationControlEntry 10 } + + ringStationTable OBJECT-TYPE + SYNTAX SEQUENCE OF RingStationEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of ring station entries. An entry will + exist for each station that is now or has + + + previously been detected as physically present on + this ring." + ::= { tokenRing 2 } + + ringStationEntry OBJECT-TYPE + SYNTAX RingStationEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for a particular + station that has been discovered on a ring + monitored by this device." + INDEX { ringStationIfIndex, ringStationMacAddress } + ::= { ringStationTable 1 } + + -- As an example, an instance of the + -- ringStationStationStatus object might be named + -- ringStationStationStatus.1.16.0.90.0.64.131 + + RingStationEntry ::= SEQUENCE { + ringStationIfIndex INTEGER, + ringStationMacAddress MacAddress, + ringStationLastNAUN MacAddress, + ringStationStationStatus INTEGER, + ringStationLastEnterTime TimeTicks, + ringStationLastExitTime TimeTicks, + ringStationDuplicateAddresses Counter, + ringStationInLineErrors Counter, + ringStationOutLineErrors Counter, + ringStationInternalErrors Counter, + ringStationInBurstErrors Counter, + ringStationOutBurstErrors Counter, + ringStationACErrors Counter, + ringStationAbortErrors Counter, + ringStationLostFrameErrors Counter, + ringStationCongestionErrors Counter, + ringStationFrameCopiedErrors Counter, + ringStationFrequencyErrors Counter, + ringStationTokenErrors Counter, + ringStationInBeaconErrors Counter, + ringStationOutBeaconErrors Counter, + ringStationInsertions Counter + } + + ringStationIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + + + DESCRIPTION + "The value of this object uniquely identifies the + interface on this remote network monitoring device + on which this station was detected. The interface + identified by a particular value of this object is + the same interface as identified by the same value + of the ifIndex object, defined in MIB-II [3]." + ::= { ringStationEntry 1 } + + ringStationMacAddress OBJECT-TYPE + SYNTAX MacAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The physical address of this station." + ::= { ringStationEntry 2 } + + ringStationLastNAUN OBJECT-TYPE + SYNTAX MacAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The physical address of last known NAUN of this + station." + ::= { ringStationEntry 3 } + + ringStationStationStatus OBJECT-TYPE + SYNTAX INTEGER { + active(1), -- actively participating in ring poll. + inactive(2), -- Not participating in ring poll + forcedRemoval(3) -- Forced off ring by network + -- management. + } + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The status of this station on the ring." + ::= { ringStationEntry 4 } + + ringStationLastEnterTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the time this station + last entered the ring. If the time is unknown, + this value shall be zero." + ::= { ringStationEntry 5 } + + + ringStationLastExitTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the time the probe + detected that this station last exited the ring. + If the time is unknown, this value shall be zero." + ::= { ringStationEntry 6 } + + ringStationDuplicateAddresses OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times this station experienced a + duplicate address error." + ::= { ringStationEntry 7 } + + ringStationInLineErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of line errors reported by this + station in error reporting packets detected by the + probe." + ::= { ringStationEntry 8 } + + ringStationOutLineErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of line errors reported in error + reporting packets sent by the nearest active + downstream neighbor of this station and detected + by the probe." + ::= { ringStationEntry 9 } + + ringStationInternalErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of adapter internal errors + reported by this station in error reporting + packets detected by the probe." + + + ::= { ringStationEntry 10 } + + ringStationInBurstErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of burst errors reported by this + station in error reporting packets detected by the + probe." + ::= { ringStationEntry 11 } + + ringStationOutBurstErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of burst errors reported in + error reporting packets sent by the nearest active + downstream neighbor of this station and detected + by the probe." + ::= { ringStationEntry 12 } + + ringStationACErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of AC (Address Copied) errors + reported in error reporting packets sent by the + nearest active downstream neighbor of this station + and detected by the probe." + ::= { ringStationEntry 13 } + + ringStationAbortErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of abort delimiters reported by + this station in error reporting packets detected + by the probe." + ::= { ringStationEntry 14 } + + ringStationLostFrameErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + + + DESCRIPTION + "The total number of lost frame errors reported by + this station in error reporting packets detected + by the probe." + ::= { ringStationEntry 15 } + + ringStationCongestionErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of receive congestion errors + reported by this station in error reporting + packets detected by the probe." + ::= { ringStationEntry 16 } + + ringStationFrameCopiedErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frame copied errors reported + by this station in error reporting packets + detected by the probe." + ::= { ringStationEntry 17 } + + ringStationFrequencyErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frequency errors reported by + this station in error reporting packets detected + by the probe." + ::= { ringStationEntry 18 } + + ringStationTokenErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of token errors reported by this + station in error reporting frames detected by the + probe." + ::= { ringStationEntry 19 } + + ringStationInBeaconErrors OBJECT-TYPE + SYNTAX Counter + + + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of beacon frames sent by this + station and detected by the probe." + ::= { ringStationEntry 20 } + + ringStationOutBeaconErrors OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of beacon frames detected by the + probe that name this station as the NAUN." + ::= { ringStationEntry 21 } + + ringStationInsertions OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The number of times the probe detected this + station inserting onto the ring." + ::= { ringStationEntry 22 } + + + -- The Token Ring Ring Station Order Group + -- + -- Implementation of this group is optional + -- + + -- The ringStationOrderTable + + ringStationOrderTable OBJECT-TYPE + SYNTAX SEQUENCE OF RingStationOrderEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of ring station entries for stations in + the ring poll, ordered by their ring-order." + ::= { tokenRing 3 } + + ringStationOrderEntry OBJECT-TYPE + SYNTAX RingStationOrderEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for a particular + + + station that is active on a ring monitored by this + device. This table will contain information for + every interface that has a + ringStationControlStatus equal to valid." + INDEX { ringStationOrderIfIndex, + ringStationOrderOrderIndex } + ::= { ringStationOrderTable 1 } + + -- As an example, an instance of the + -- ringStationOrderMacAddress object might be named + -- ringStationOrderMacAddress.1.14 + + RingStationOrderEntry ::= SEQUENCE { + ringStationOrderIfIndex INTEGER, + ringStationOrderOrderIndex INTEGER, + ringStationOrderMacAddress MacAddress + } + + ringStationOrderIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies the + interface on this remote network monitoring device + on which this station was detected. The interface + identified by a particular value of this object is + the same interface as identified by the same value + of the ifIndex object, defined in MIB-II [3]." + ::= { ringStationOrderEntry 1 } + + ringStationOrderOrderIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "This index denotes the location of this station + with respect to other stations on the ring. This + index is one more than the number of hops + downstream that this station is from the rmon + probe. The rmon probe itself gets the value one." + ::= { ringStationOrderEntry 2 } + + ringStationOrderMacAddress OBJECT-TYPE + SYNTAX MacAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + + + "The physical address of this station." + ::= { ringStationOrderEntry 3 } + + + -- The Token Ring Ring Station Config Group + -- + -- Implementation of this group is optional. + -- The ring station config group manages token ring nodes + -- through active means. + + ringStationConfigControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF RingStationConfigControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of ring station configuration control + entries." + ::= { tokenRing 4 } + + ringStationConfigControlEntry OBJECT-TYPE + SYNTAX RingStationConfigControlEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "This entry controls active management of stations + by the probe. One entry exists in this table for + each active station in the ringStationTable." + INDEX { ringStationConfigControlIfIndex, + ringStationConfigControlMacAddress } + ::= { ringStationConfigControlTable 1 } + + -- As an example, an instance of the + -- ringStationConfigControlRemove object might be named + -- ringStationConfigControlRemove.1.16.0.90.0.64.131 + + RingStationConfigControlEntry ::= SEQUENCE { + ringStationConfigControlIfIndex INTEGER, + ringStationConfigControlMacAddress MacAddress, + ringStationConfigControlRemove INTEGER, + ringStationConfigControlUpdateStats INTEGER + } + + ringStationConfigControlIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies the + + + interface on this remote network monitoring device + on which this station was detected. The interface + identified by a particular value of this object is + the same interface as identified by the same value + of the ifIndex object, defined in MIB-II [3]." + ::= { ringStationConfigControlEntry 1 } + + ringStationConfigControlMacAddress OBJECT-TYPE + SYNTAX MacAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The physical address of this station." + ::= { ringStationConfigControlEntry 2 } + + ringStationConfigControlRemove OBJECT-TYPE + SYNTAX INTEGER { + stable(1), + removing(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Setting this object to `removing(2)' causes a + Remove Station MAC frame to be sent. The agent + will set this object to `stable(1)' after + processing the request." + ::= { ringStationConfigControlEntry 3 } + + ringStationConfigControlUpdateStats OBJECT-TYPE + SYNTAX INTEGER { + stable(1), + updating(2) + } + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Setting this object to `updating(2)' causes the + configuration information associate with this + entry to be updated. The agent will set this + object to `stable(1)' after processing the + request." + ::= { ringStationConfigControlEntry 4 } + + + + + + + + -- The ringStationConfig Table + -- + -- Entries exist in this table after an active + -- configuration query has completed successfully for + -- a station. This query is initiated by the associated + -- ringStationConfigControlUpdateStats variable. + + ringStationConfigTable OBJECT-TYPE + SYNTAX SEQUENCE OF RingStationConfigEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of configuration entries for stations on a + ring monitored by this probe." + ::= { tokenRing 5 } + + ringStationConfigEntry OBJECT-TYPE + SYNTAX RingStationConfigEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of statistics for a particular + station that has been discovered on a ring + monitored by this probe." + INDEX { ringStationConfigIfIndex, + ringStationConfigMacAddress } + ::= { ringStationConfigTable 1 } + + -- As an example, an instance of the + -- ringStationConfigLocation object might be named + -- ringStationConfigLocation.1.16.0.90.0.64.131 + + RingStationConfigEntry ::= SEQUENCE { + ringStationConfigIfIndex INTEGER, + ringStationConfigMacAddress MacAddress, + ringStationConfigUpdateTime TimeTicks, + ringStationConfigLocation OCTET STRING, + ringStationConfigMicrocode OCTET STRING, + ringStationConfigGroupAddress OCTET STRING, + ringStationConfigFunctionalAddress OCTET STRING + } + + ringStationConfigIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies the + + + interface on this remote network monitoring device + on which this station was detected. The interface + identified by a particular value of this object is + the same interface as identified by the same value + of the ifIndex object, defined in MIB-II [3]." + ::= { ringStationConfigEntry 1 } + + ringStationConfigMacAddress OBJECT-TYPE + SYNTAX MacAddress + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The physical address of this station." + ::= { ringStationConfigEntry 2 } + + ringStationConfigUpdateTime OBJECT-TYPE + SYNTAX TimeTicks + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of sysUpTime at the time this + configuration information was last updated + (completely)." + ::= { ringStationConfigEntry 3 } + + ringStationConfigLocation OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(4)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The assigned physical location of this station." + ::= { ringStationConfigEntry 4 } + + ringStationConfigMicrocode OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(10)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The microcode EC level of this station." + ::= { ringStationConfigEntry 5 } + + ringStationConfigGroupAddress OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(4)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The low-order 4 octets of the group address + recognized by this station." + + + ::= { ringStationConfigEntry 6 } + + ringStationConfigFunctionalAddress OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(4)) + ACCESS read-only + STATUS mandatory + DESCRIPTION + "the functional addresses recognized by this + station." + ::= { ringStationConfigEntry 7 } + + + -- The Token Ring Source Routing group + -- + -- Implementation of this group is optional. + -- The data in this group is collected from the source + -- routing information potentially present in any token ring + -- packet. This information will be valid only in a pure + -- source route bridging environment. In a transparent + -- bridging or a mixed bridging environment, this + -- information may not be accurate. + + sourceRoutingStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF SourceRoutingStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of source routing statistics entries." + ::= { tokenRing 6 } + + sourceRoutingStatsEntry OBJECT-TYPE + SYNTAX SourceRoutingStatsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A collection of source routing statistics kept + for a particular Token Ring interface." + INDEX { sourceRoutingStatsIfIndex } + ::= { sourceRoutingStatsTable 1 } + + -- As an example, an instance of the + -- sourceRoutingStatsInFrames object might be named + -- sourceRoutingStatsInFrames.1 + + SourceRoutingStatsEntry ::= SEQUENCE { + sourceRoutingStatsIfIndex INTEGER, + sourceRoutingStatsRingNumber INTEGER, + sourceRoutingStatsInFrames Counter, + + + -- in to our net + + sourceRoutingStatsOutFrames Counter, + -- out from our net + + sourceRoutingStatsThroughFrames Counter, + -- through our net + + sourceRoutingStatsAllRoutesBroadcastFrames Counter, + sourceRoutingStatsSingleRouteBroadcastFrames Counter, + sourceRoutingStatsInOctets Counter, + sourceRoutingStatsOutOctets Counter, + sourceRoutingStatsThroughOctets Counter, + sourceRoutingStatsAllRoutesBroadcastOctets Counter, + sourceRoutingStatsSingleRoutesBroadcastOctets Counter, + sourceRoutingStatsLocalLLCFrames Counter, + sourceRoutingStats1HopFrames Counter, + sourceRoutingStats2HopsFrames Counter, + sourceRoutingStats3HopsFrames Counter, + sourceRoutingStats4HopsFrames Counter, + sourceRoutingStats5HopsFrames Counter, + sourceRoutingStats6HopsFrames Counter, + sourceRoutingStats7HopsFrames Counter, + sourceRoutingStats8HopsFrames Counter, + sourceRoutingStatsMoreThan8HopsFrames Counter, + sourceRoutingStatsOwner OwnerString, + sourceRoutingStatsStatus EntryStatus + } + + sourceRoutingStatsIfIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The value of this object uniquely identifies the + interface on this remote network monitoring device + on which source routing statistics will be + detected. The interface identified by a + particular value of this object is the same + interface as identified by the same value of the + ifIndex object, defined in MIB-II [3]." + ::= { sourceRoutingStatsEntry 1 } + + sourceRoutingStatsRingNumber OBJECT-TYPE + SYNTAX INTEGER + ACCESS read-only + STATUS mandatory + DESCRIPTION + + + "The ring number of the ring monitored by this + entry. When any object in this entry is created, + the probe will attempt to discover the ring + number. Only after the ring number is discovered + will this object be created. After creating an + object in this entry, the management station + should poll this object to detect when it is + created. Only after this object is created can + the management station set the + sourceRoutingStatsStatus entry to valid(1)." + ::= { sourceRoutingStatsEntry 2 } + + sourceRoutingStatsInFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The count of frames sent into this ring from + another ring." + ::= { sourceRoutingStatsEntry 3 } + + sourceRoutingStatsOutFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The count of frames sent from this ring to + another ring." + ::= { sourceRoutingStatsEntry 4 } + + sourceRoutingStatsThroughFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The count of frames sent from another ring, + through this ring, to another ring." + ::= { sourceRoutingStatsEntry 5 } + + sourceRoutingStatsAllRoutesBroadcastFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good frames received that + were All Routes Broadcast." + ::= { sourceRoutingStatsEntry 6 } + + + + sourceRoutingStatsSingleRouteBroadcastFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of good frames received that + were Single Route Broadcast." + ::= { sourceRoutingStatsEntry 7 } + + sourceRoutingStatsInOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The count of octets in good frames sent into this + ring from another ring." + ::= { sourceRoutingStatsEntry 8 } + + sourceRoutingStatsOutOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The count of octets in good frames sent from this + ring to another ring." + ::= { sourceRoutingStatsEntry 9 } + + sourceRoutingStatsThroughOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The count of octets in good frames sent another + ring, through this ring, to another ring." + ::= { sourceRoutingStatsEntry 10 } + + sourceRoutingStatsAllRoutesBroadcastOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of octets in good frames + received that were All Routes Broadcast." + ::= { sourceRoutingStatsEntry 11 } + + sourceRoutingStatsSingleRoutesBroadcastOctets OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + + + STATUS mandatory + DESCRIPTION + "The total number of octets in good frames + received that were Single Route Broadcast." + ::= { sourceRoutingStatsEntry 12 } + + sourceRoutingStatsLocalLLCFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frames received who had no + RIF field (or had a RIF field that only included + the local ring's number) and were not All Route + Broadcast Frames." + ::= { sourceRoutingStatsEntry 13 } + + sourceRoutingStats1HopFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frames received whose route + had 1 hop, were not All Route Broadcast Frames, + and whose source or destination were on this ring + (i.e. frames that had a RIF field and had this + ring number in the first or last entry of the RIF + field)." + ::= { sourceRoutingStatsEntry 14 } + + sourceRoutingStats2HopsFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frames received whose route + had 2 hops, were not All Route Broadcast Frames, + and whose source or destination were on this ring + (i.e. frames that had a RIF field and had this + ring number in the first or last entry of the RIF + field)." + ::= { sourceRoutingStatsEntry 15 } + + sourceRoutingStats3HopsFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + + + "The total number of frames received whose route + had 3 hops, were not All Route Broadcast Frames, + and whose source or destination were on this ring + (i.e. frames that had a RIF field and had this + ring number in the first or last entry of the RIF + field)." + ::= { sourceRoutingStatsEntry 16 } + + sourceRoutingStats4HopsFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frames received whose route + had 4 hops, were not All Route Broadcast Frames, + and whose source or destination were on this ring + (i.e. frames that had a RIF field and had this + ring number in the first or last entry of the RIF + field)." + ::= { sourceRoutingStatsEntry 17 } + + sourceRoutingStats5HopsFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frames received whose route + had 5 hops, were not All Route Broadcast Frames, + and whose source or destination were on this ring + (i.e. frames that had a RIF field and had this + ring number in the first or last entry of the RIF + field)." + ::= { sourceRoutingStatsEntry 18 } + + sourceRoutingStats6HopsFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frames received whose route + had 6 hops, were not All Route Broadcast Frames, + and whose source or destination were on this ring + (i.e. frames that had a RIF field and had this + ring number in the first or last entry of the RIF + field)." + ::= { sourceRoutingStatsEntry 19 } + + sourceRoutingStats7HopsFrames OBJECT-TYPE + + + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frames received whose route + had 7 hops, were not All Route Broadcast Frames, + and whose source or destination were on this ring + (i.e. frames that had a RIF field and had this + ring number in the first or last entry of the RIF + field)." + ::= { sourceRoutingStatsEntry 20 } + + sourceRoutingStats8HopsFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frames received whose route + had 8 hops, were not All Route Broadcast Frames, + and whose source or destination were on this ring + (i.e. frames that had a RIF field and had this + ring number in the first or last entry of the RIF + field)." + ::= { sourceRoutingStatsEntry 21 } + + sourceRoutingStatsMoreThan8HopsFrames OBJECT-TYPE + SYNTAX Counter + ACCESS read-only + STATUS mandatory + DESCRIPTION + "The total number of frames received whose route + had more than 8 hops, were not All Route Broadcast + Frames, and whose source or destination were on + this ring (i.e. frames that had a RIF field and + had this ring number in the first or last entry of + the RIF field)." + ::= { sourceRoutingStatsEntry 22 } + + sourceRoutingStatsOwner OBJECT-TYPE + SYNTAX OwnerString + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The entity that configured this entry and is + therefore using the resources assigned to it." + ::= { sourceRoutingStatsEntry 23 } + + sourceRoutingStatsStatus OBJECT-TYPE + + + SYNTAX EntryStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this sourceRoutingStats entry." + ::= { sourceRoutingStatsEntry 24 } + + END diff --git a/lib/snmp/test/test-mibs/Table1-error.mib b/lib/snmp/test/test-mibs/Table1-error.mib new file mode 100644 index 0000000000..d2d38c14ef --- /dev/null +++ b/lib/snmp/test/test-mibs/Table1-error.mib @@ -0,0 +1,97 @@ + Table1-error DEFINITIONS ::= BEGIN + + IMPORTS + OBJECT-TYPE + FROM RFC-1212; + + klas1 OBJECT IDENTIFIER ::= { private 7 } + + RowStatus ::= + INTEGER { + -- the following two values are states: + -- these values may be read or written + active(1), + notInService(2), + + -- the following value is a state: + -- this value may be read, but not written + notReady(3), + + -- the following three values are + -- actions: these values may be written, + -- but are never read + createAndGo(4), + createAndWait(5), + destroy(6) + } + + + friendsTable OBJECT-TYPE + SYNTAX SEQUENCE OF FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "A list of klas friends." + ::= { klas1 4 } + + friendsEntry OBJECT-TYPE + SYNTAX FriendsEntry + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "nope" + INDEX { fIndex } + ::= { friendsTable 1 } + + FriendsEntry ::= + SEQUENCE { + fIndex + INTEGER, + fName + OCTET STRING, + fStatus + INTEGER } + + fName OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + ACCESS read-write + STATUS mandatory + DESCRIPTION + "Name of friend" + ::= { friendsEntry 2 } + +-- this is perhaps not really an error. +-- a _nice_ compiler should allow columns to be defined in any order. + + fIndex OBJECT-TYPE + SYNTAX INTEGER + ACCESS not-accessible + STATUS mandatory + DESCRIPTION + "number of friend" + ::= { friendsEntry 1 } + + fStatus OBJECT-TYPE + SYNTAX RowStatus + ACCESS read-write + STATUS mandatory + DESCRIPTION + "The status of this conceptual row." + ::= { friendsEntry 3 } + + authenticationFajlure TRAP-TYPE + ENTERPRISE klas1 + DESCRIPTION + "An authenticationFailure trap signifies that + the sending protocol entity is the addressee + of a protocol message that is not properly + authenticated. While implementations of the + SNMP must be capable of generating this trap, + they must also be capable of suppressing the + emission of such traps via an implementation- + specific mechanism." + ::= 4 + + + END + diff --git a/lib/snmp/test/test-mibs/Type-error.mib b/lib/snmp/test/test-mibs/Type-error.mib new file mode 100644 index 0000000000..6361679d47 --- /dev/null +++ b/lib/snmp/test/test-mibs/Type-error.mib @@ -0,0 +1,11 @@ +Type-error DEFINITIONS ::= BEGIN + + IMPORTS + OBJECT-TYPE + FROM RFC-1212; + + Q ::= INTEGER + Q ::= INTEGER + + END + diff --git a/lib/snmp/test/test1.erl b/lib/snmp/test/test1.erl new file mode 100644 index 0000000000..b26b03d4ce --- /dev/null +++ b/lib/snmp/test/test1.erl @@ -0,0 +1,72 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(test1). + +-compile(export_all). + +bits1(get) -> + {value, [b0, b2]}. +bits1(set, _) -> + noError. + +bits2(get) -> + {value, 2#11000000110}. +bits2(set, _) -> + noError. + +bits3(get) -> + {value, [b0, b4]}. % error! + +bits4(get) -> + {value, 2#1000}. % error! + +opaque_obj(get) -> + {value, "opaque-data"}. + +cnt64(get) -> + {value, 18446744073709551615}. + +multiStr(get) -> + i("multiStr(get) -> entry"), + global:re_register_name(snmp_multi_tester, self()), + i("multiStr(get) -> registered, now await continue"), + receive + continue -> + i("multiStr(get) -> received continue"), + ok + end, + {value, "ok"}. + +multiStr(set, "block") -> + global:re_register_name(snmp_multi_tester, self()), + receive + continue -> ok + end, + noError; +multiStr(set, _Value) -> + noError. + + +i(F) -> + i(F, []). + +i(F, A) -> + io:format("~p ~w:" ++ F ++ "~n", [self(), ?MODULE | A]). + diff --git a/lib/snmp/test/test2.erl b/lib/snmp/test/test2.erl new file mode 100644 index 0000000000..dc010cfa11 --- /dev/null +++ b/lib/snmp/test/test2.erl @@ -0,0 +1,80 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(test2). + +-compile(export_all). + +%%----------------------------------------------------------------- +%% Implements the Test2 MIB. Used to test processing +%% of requests. +%%----------------------------------------------------------------- +tDescr(get, 2) -> + {noValue, noSuchName}; +tDescr(get, 3) -> + {noValue, noSuchInstance}; +tDescr(get, 4) -> + {noValue, noSuchObject}. + +tDescr(is_set_ok, "badValue", 2) -> + badValue; +tDescr(is_set_ok, "inconsistentValue", 2) -> + inconsistentValue; +tDescr(is_set_ok, "resourceUnavailable", 2) -> + resourceUnavailable; +tDescr(is_set_ok, "inconsistentName", 2) -> + inconsistentName; +tDescr(is_set_ok, "is_set_ok_fail", 2) -> + genErr; +tDescr(set, "commit_fail", 2) -> + commitFailed. + +tGenErr(get, 1) -> + genErr; +tGenErr(get, 2) -> + 1=2; +tGenErr(get, 3) -> + {value, "not an integer, I know"}. + +tInt(is_set_ok, 5, 3) -> + wrongValue. + + +tTable(is_set_ok, [1,1], [{2, "noCreation"}]) -> + {noCreation, 2}; +tTable(is_set_ok, [1,2], [{2, "inconsistentName"}]) -> + {inconsistentName, 2}; +tTable(get_next, _RowIndex, Cols) -> + lists:map(fun(_) -> endOfTable end, Cols). + +%% Only 2 reqs are valid: +%% gn([[tCnt2, 1]]) +%% gn([[tCnt2, 2]]) +%% ... or as: +%% gb(0, 2, [[tCnt2,1]]) +tTable2(get_next, [1], [2]) -> + [{[2,2], 100}]; +tTable2(get_next, [2], [2]) -> + [endOfTable]. + + + + +tTooBig(get) -> + {value, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}. |