aboutsummaryrefslogtreecommitdiffstats
path: root/lib/snmp/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/snmp/test')
-rw-r--r--lib/snmp/test/Makefile259
-rw-r--r--lib/snmp/test/klas3.erl162
-rw-r--r--lib/snmp/test/modules.mk76
-rw-r--r--lib/snmp/test/sa.erl44
-rw-r--r--lib/snmp/test/snmp.cover15
-rw-r--r--lib/snmp/test/snmp.spec1
-rw-r--r--lib/snmp/test/snmp.spec.vxworks4
-rw-r--r--lib/snmp/test/snmp_SUITE.erl157
-rw-r--r--lib/snmp/test/snmp_agent_bl_test.erl5654
-rw-r--r--lib/snmp/test/snmp_agent_mibs_test.erl721
-rw-r--r--lib/snmp/test/snmp_agent_ms_test.erl5657
-rw-r--r--lib/snmp/test/snmp_agent_mt_test.erl5657
-rw-r--r--lib/snmp/test/snmp_agent_nfilter_test.erl78
-rw-r--r--lib/snmp/test/snmp_agent_test.erl6009
-rw-r--r--lib/snmp/test/snmp_agent_test_lib.erl1480
-rw-r--r--lib/snmp/test/snmp_agent_v1_test.erl2673
-rw-r--r--lib/snmp/test/snmp_agent_v2_test.erl5657
-rw-r--r--lib/snmp/test/snmp_agent_v3_test.erl5657
-rw-r--r--lib/snmp/test/snmp_app_test.erl430
-rw-r--r--lib/snmp/test/snmp_appup_mgr.erl280
-rw-r--r--lib/snmp/test/snmp_appup_test.erl560
-rw-r--r--lib/snmp/test/snmp_compiler_test.erl391
-rw-r--r--lib/snmp/test/snmp_conf_test.erl680
-rw-r--r--lib/snmp/test/snmp_log_test.erl941
-rw-r--r--lib/snmp/test/snmp_manager_config_test.erl2535
-rw-r--r--lib/snmp/test/snmp_manager_test.erl5436
-rw-r--r--lib/snmp/test/snmp_manager_user.erl935
-rwxr-xr-xlib/snmp/test/snmp_manager_user_old.erl264
-rw-r--r--lib/snmp/test/snmp_manager_user_test.erl1244
-rw-r--r--lib/snmp/test/snmp_manager_user_test_lib.erl422
-rw-r--r--lib/snmp/test/snmp_note_store_test.erl306
-rw-r--r--lib/snmp/test/snmp_pdus_test.erl127
-rw-r--r--lib/snmp/test/snmp_test_data/ERICSSON-TOP-MIB.mib36
-rw-r--r--lib/snmp/test/snmp_test_data/EX1-MIB.mib90
-rw-r--r--lib/snmp/test/snmp_test_data/Klas1-v2.mib128
-rw-r--r--lib/snmp/test/snmp_test_data/Klas1.mib116
-rw-r--r--lib/snmp/test/snmp_test_data/Klas2.funcs3
-rw-r--r--lib/snmp/test/snmp_test_data/Klas2.mib128
-rw-r--r--lib/snmp/test/snmp_test_data/Klas3.funcs2
-rw-r--r--lib/snmp/test/snmp_test_data/Klas3.mib40
-rw-r--r--lib/snmp/test/snmp_test_data/Klas4.funcs3
-rw-r--r--lib/snmp/test/snmp_test_data/Klas4.mib156
-rw-r--r--lib/snmp/test/snmp_test_data/OLD-SNMPEA-MIB-v2.mib480
-rw-r--r--lib/snmp/test/snmp_test_data/OLD-SNMPEA-MIB.mib487
-rw-r--r--lib/snmp/test/snmp_test_data/PROXY.mib60
-rw-r--r--lib/snmp/test/snmp_test_data/RFC1213-MIB.mib2888
-rw-r--r--lib/snmp/test/snmp_test_data/SA-MIB.funcs5
-rw-r--r--lib/snmp/test/snmp_test_data/SA-MIB.mib93
-rw-r--r--lib/snmp/test/snmp_test_data/SNMPv2-MIB.funcs28
-rw-r--r--lib/snmp/test/snmp_test_data/SNMPv2-MIB.mib767
-rw-r--r--lib/snmp/test/snmp_test_data/STANDARD-MIB.funcs8
-rw-r--r--lib/snmp/test/snmp_test_data/STANDARD-MIB.mib528
-rw-r--r--lib/snmp/test/snmp_test_data/Test1.funcs7
-rw-r--r--lib/snmp/test/snmp_test_data/Test1.mib370
-rw-r--r--lib/snmp/test/snmp_test_data/Test2.funcs10
-rw-r--r--lib/snmp/test/snmp_test_data/Test2.mib246
-rw-r--r--lib/snmp/test/snmp_test_data/TestTrap.mib44
-rw-r--r--lib/snmp/test/snmp_test_data/TestTrapv2.mib71
-rw-r--r--lib/snmp/test/snmp_test_lib.erl525
-rw-r--r--lib/snmp/test/snmp_test_lib.hrl151
-rw-r--r--lib/snmp/test/snmp_test_manager.erl388
-rw-r--r--lib/snmp/test/snmp_test_mgr.erl1139
-rw-r--r--lib/snmp/test/snmp_test_mgr_misc.erl792
-rw-r--r--lib/snmp/test/snmp_test_server.erl416
-rw-r--r--lib/snmp/test/snmp_test_suite.erl35
-rw-r--r--lib/snmp/test/test-mibs/Bitsindex-error.mib94
-rw-r--r--lib/snmp/test/test-mibs/ENTITY-MIB.mib784
-rw-r--r--lib/snmp/test/test-mibs/INTERNAL-MIB.mib463
-rw-r--r--lib/snmp/test/test-mibs/Klas1.mib118
-rw-r--r--lib/snmp/test/test-mibs/Oid1-error.mib26
-rw-r--r--lib/snmp/test/test-mibs/README19
-rw-r--r--lib/snmp/test/test-mibs/RFC1213-MIB.mib2888
-rw-r--r--lib/snmp/test/test-mibs/RFC1271-MIB.mib3492
-rw-r--r--lib/snmp/test/test-mibs/RMON-MIB.mib3826
-rw-r--r--lib/snmp/test/test-mibs/RMON2-MIB.mib5450
-rw-r--r--lib/snmp/test/test-mibs/SNMPv2-MIB.mib777
-rw-r--r--lib/snmp/test/test-mibs/SNMPv2-TC.mib799
-rw-r--r--lib/snmp/test/test-mibs/SNMPv2-USEC-MIB.mib251
-rw-r--r--lib/snmp/test/test-mibs/SNMPv2-test.mib777
-rw-r--r--lib/snmp/test/test-mibs/STANDARD-MIB.mib518
-rw-r--r--lib/snmp/test/test-mibs/TOKEN-RING-RMON-MIB.mib2406
-rw-r--r--lib/snmp/test/test-mibs/Table1-error.mib97
-rw-r--r--lib/snmp/test/test-mibs/Type-error.mib11
-rw-r--r--lib/snmp/test/test1.erl72
-rw-r--r--lib/snmp/test/test2.erl80
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
+
+ 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
+
+ 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
+
+
+ Andy Bierman (WG Chair)
+ Phone: +1 805 648 2028
+ 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
+
+ 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
+
+ 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
+
+ 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"}.