diff options
Diffstat (limited to 'lib/snmp/examples')
-rw-r--r-- | lib/snmp/examples/Makefile | 35 | ||||
-rw-r--r-- | lib/snmp/examples/ex1/EX1-MIB.funcs | 2 | ||||
-rw-r--r-- | lib/snmp/examples/ex1/EX1-MIB.mib | 90 | ||||
-rw-r--r-- | lib/snmp/examples/ex1/EX1-MIBv2.funcs | 2 | ||||
-rw-r--r-- | lib/snmp/examples/ex1/EX1-MIBv2.mib | 104 | ||||
-rw-r--r-- | lib/snmp/examples/ex1/Makefile | 97 | ||||
-rw-r--r-- | lib/snmp/examples/ex1/ex1.erl | 256 | ||||
-rw-r--r-- | lib/snmp/examples/ex2/Makefile | 93 | ||||
-rw-r--r-- | lib/snmp/examples/ex2/snmp_ex2_manager.erl | 407 | ||||
-rw-r--r-- | lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl | 287 | ||||
-rw-r--r-- | lib/snmp/examples/mcli/.gitignore | 0 | ||||
-rw-r--r-- | lib/snmp/examples/subdirs.mk | 21 |
12 files changed, 1394 insertions, 0 deletions
diff --git a/lib/snmp/examples/Makefile b/lib/snmp/examples/Makefile new file mode 100644 index 0000000000..341107ce30 --- /dev/null +++ b/lib/snmp/examples/Makefile @@ -0,0 +1,35 @@ +#-*-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% + +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Common Macros +# ---------------------------------------------------- + +include subdirs.mk + +SPECIAL_TARGETS = + +# ---------------------------------------------------- +# Default Subdir Targets +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_subdir.mk + diff --git a/lib/snmp/examples/ex1/EX1-MIB.funcs b/lib/snmp/examples/ex1/EX1-MIB.funcs new file mode 100644 index 0000000000..0ae1db6541 --- /dev/null +++ b/lib/snmp/examples/ex1/EX1-MIB.funcs @@ -0,0 +1,2 @@ +{myName, {ex1, my_name, []}}. +{friendsTable, {ex1, friends_table, []}}. diff --git a/lib/snmp/examples/ex1/EX1-MIB.mib b/lib/snmp/examples/ex1/EX1-MIB.mib new file mode 100644 index 0000000000..5d9979d0b4 --- /dev/null +++ b/lib/snmp/examples/ex1/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/examples/ex1/EX1-MIBv2.funcs b/lib/snmp/examples/ex1/EX1-MIBv2.funcs new file mode 100644 index 0000000000..0ae1db6541 --- /dev/null +++ b/lib/snmp/examples/ex1/EX1-MIBv2.funcs @@ -0,0 +1,2 @@ +{myName, {ex1, my_name, []}}. +{friendsTable, {ex1, friends_table, []}}. diff --git a/lib/snmp/examples/ex1/EX1-MIBv2.mib b/lib/snmp/examples/ex1/EX1-MIBv2.mib new file mode 100644 index 0000000000..e7250c4a63 --- /dev/null +++ b/lib/snmp/examples/ex1/EX1-MIBv2.mib @@ -0,0 +1,104 @@ +EX1-MIBv2 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} + + + myName OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-write + STATUS current + DESCRIPTION + "My own name" + ::= { 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 deprecated + 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 } + +friendGroup OBJECT-GROUP + OBJECTS { myName, fIndex, fName,fAddress, fStatus } + STATUS current + DESCRIPTION " A object group" + ::= { example1 2 } + +END diff --git a/lib/snmp/examples/ex1/Makefile b/lib/snmp/examples/ex1/Makefile new file mode 100644 index 0000000000..1a55ba0470 --- /dev/null +++ b/lib/snmp/examples/ex1/Makefile @@ -0,0 +1,97 @@ +#-*-makefile-*- ; force emacs to enter makefile-mode + +# %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% + +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../../vsn.mk + +VSN = $(SNMP_VSN) + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +ifneq ($(MIBS_VERBOSITY),) +SNMP_FLAGS += +'{verbosity,$(MIBS_VERBOSITY)}' +endif + +ERL_COMPILE_FLAGS += -I../include \ + -Dversion=\"$(VSN)$(PRE_VSN)\" \ + +'{parse_transform,sys_pre_attributes}' \ + +'{attribute,insert,app_vsn,$(APP_VSN)}' \ + -I$(ERL_TOP)/lib/stdlib \ + $(SNMP_FLAGS) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/snmp-$(VSN) +EXAMPLE_RELSYSDIR = $(RELSYSDIR)/examples +EX1_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/ex1 + +# ---------------------------------------------------- +# Common macros +# ---------------------------------------------------- + +ERL_FILES = ex1.erl +MIB_FILES = EX1-MIB.funcs EX1-MIB.mib +BUILD_MIBS = EX1-MIB + +TARGET_FILES= \ + $(BUILD_MIBS:%=%.bin) \ + $(ERL_FILES:%.erl=%.$(EMULATOR)) + + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +debug opt: build + +clean: + rm -f $(TARGET_FILES) + rm -f core *~ + +docs: + +build: $(TARGET_FILES) + + +info: + @echo "TARGET_FILES: $(TARGET_FILES)" + @echo "EXAMPLE_FILES: $(EXAMPLE_FILES)" + + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + $(INSTALL_DIR) $(EXAMPLE_RELSYSDIR) + $(INSTALL_DIR) $(EX1_RELSYSDIR) + $(INSTALL_DATA) $(MIB_FILES) $(EX1_RELSYSDIR) + $(INSTALL_DATA) $(ERL_FILES) $(EX1_RELSYSDIR) + $(INSTALL_DATA) $(TARGET_FILES) $(EX1_RELSYSDIR) + +release_docs_spec: diff --git a/lib/snmp/examples/ex1/ex1.erl b/lib/snmp/examples/ex1/ex1.erl new file mode 100644 index 0000000000..3618cd3b8c --- /dev/null +++ b/lib/snmp/examples/ex1/ex1.erl @@ -0,0 +1,256 @@ +%%<copyright> +%% <year>1996-2007</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> +%% +-module(ex1). + +%% External exports +-export([start/0, my_name/1, my_name/2, friends_table/3]). + +%% Internal exports +-export([init/0]). + +-define(status_col, 4). + +-define(active, 1). +-define(notInService, 2). +-define(notReady, 3). +-define(createAndGo, 4). % Action; written, not read +-define(createAndWait, 5). % Action; written, not read +-define(destroy, 6). % Action; written, not read + +start() -> + spawn(ex1, init, []). + + +%%---------------------------------------------------------------- +%% Instrumentation function for variable myName. +%% Returns: (get) {value, Name} +%% (set) noError +%%---------------------------------------------------------------- +my_name(get) -> + ex1_server ! {self(), get_my_name}, + Name = wait_answer(), + {value, Name}. + +my_name(set, NewName) -> + ex1_server ! {self(), {set_my_name, NewName}}, + noError. + +%%---------------------------------------------------------------- +%% Instrumentation function for table friendsTable. +%%---------------------------------------------------------------- +friends_table(get, RowIndex, Cols) -> + case get_row(RowIndex) of + {ok, Row} -> + get_cols(Cols, Row); + _ -> + {noValue, noSuchInstance} + end; + +friends_table(get_next, RowIndex, Cols) -> + case get_next_row(RowIndex) of + {ok, Row} -> + get_next_cols(Cols, Row); + _ -> + case get_next_row([]) of + {ok, Row} -> + % Get next cols from first row. + NewCols = add_one_to_cols(Cols), + get_next_cols(NewCols, Row); + _ -> + end_of_table(Cols) + end + end; + +%%---------------------------------------------------------------- +%% If RowStatus is set, then: +%% *) If set to destroy, check that row does exist +%% *) If set to createAndGo, check that row doesn't exist AND +%% that all columns are given values. +%% *) Otherwise, error (for simplicity). +%% Otherwise, row is modified; check that row exists. +%%---------------------------------------------------------------- +friends_table(is_set_ok, RowIndex, Cols) -> + RowExists = + case get_row(RowIndex) of + {ok, _Row} -> true; + _ -> false + end, + case is_row_status_col_changed(Cols) of + {true, ?destroy} when RowExists == true -> + {noError, 0}; + {true, ?createAndGo} when RowExists == false, + length(Cols) == 3 -> + {noError, 0}; + {true, _} -> + {inconsistentValue, ?status_col}; + false when RowExists == true -> + {noError, 0}; + _ -> + [{Col, _NewVal} | _Cols] = Cols, + {inconsistentName, Col} + end; + +friends_table(set, RowIndex, Cols) -> + case is_row_status_col_changed(Cols) of + {true, ?destroy} -> + ex1_server ! {self(), {delete_row, RowIndex}}; + {true, ?createAndGo} -> + NewRow = make_row(RowIndex, Cols), + ex1_server ! {self(), {add_row, NewRow}}; + false -> + {ok, Row} = get_row(RowIndex), + NewRow = merge_rows(Row, Cols), + ex1_server ! {self(), {delete_row, RowIndex}}, + ex1_server ! {self(), {add_row, NewRow}} + end, + {noError, 0}. + +%%---------------------------------------------------------------- +%% Make a list of {value, Val} of the Row and Cols list. +%%---------------------------------------------------------------- +get_cols([Col | Cols], Row) -> + [{value, element(Col, Row)} | get_cols(Cols, Row)]; +get_cols([], _Row) -> + []. + +%%---------------------------------------------------------------- +%% As get_cols, but the Cols list may contain invalid column +%% numbers. If it does, we must find the next valid column, +%% or return endOfTable. +%%---------------------------------------------------------------- +get_next_cols([Col | Cols], Row) when Col < 2 -> + [{[2, element(1, Row)], element(2, Row)} | + get_next_cols(Cols, Row)]; +get_next_cols([Col | Cols], Row) when Col > 4 -> + [endOfTable | + get_next_cols(Cols, Row)]; +get_next_cols([Col | Cols], Row) -> + [{[Col, element(1, Row)], element(Col, Row)} | + get_next_cols(Cols, Row)]; +get_next_cols([], _Row) -> + []. + +%%---------------------------------------------------------------- +%% Make a list of endOfTable with as many elems as Cols list. +%%---------------------------------------------------------------- +end_of_table([_Col | Cols]) -> + [endOfTable | end_of_table(Cols)]; +end_of_table([]) -> + []. + +add_one_to_cols([Col | Cols]) -> + [Col + 1 | add_one_to_cols(Cols)]; +add_one_to_cols([]) -> + []. + +is_row_status_col_changed(Cols) -> + case lists:keysearch(?status_col, 1, Cols) of + {value, {?status_col, StatusVal}} -> + {true, StatusVal}; + _ -> false + end. + +get_row(RowIndex) -> + ex1_server ! {self(), {get_row, RowIndex}}, + wait_answer(). + +get_next_row(RowIndex) -> + ex1_server ! {self(), {get_next_row, RowIndex}}, + wait_answer(). + +wait_answer() -> + receive + {ex1_server, Answer} -> + Answer + end. + +%%%---------------------------------------------------------------- +%%% Server code follows +%%%---------------------------------------------------------------- +init() -> + register(ex1_server, self()), + loop("", []). + +loop(MyName, Table) -> + receive + {From, get_my_name} -> + From ! {ex1_server, MyName}, + loop(MyName, Table); + {_From, {set_my_name, NewName}} -> + loop(NewName, Table); + {From, {get_row, RowIndex}} -> + Res = table_get_row(Table, RowIndex), + From ! {ex1_server, Res}, + loop(MyName, Table); + {From, {get_next_row, RowIndex}} -> + Res = table_get_next_row(Table, RowIndex), + From ! {ex1_server, Res}, + loop(MyName, Table); + {_From, {delete_row, RowIndex}} -> + NewTable = table_delete_row(Table, RowIndex), + loop(MyName, NewTable); + {_From, {add_row, NewRow}} -> + NewTable = table_add_row(Table, NewRow), + loop(MyName, NewTable) + end. + + +%%----------------------------------------------------------------- +%% Implementation of the table. +%%----------------------------------------------------------------- +table_get_row([{Index, Name, Address, Status} | _], [Index]) -> + {ok, {Index, Name, Address, Status}}; +table_get_row([_H | T], RowIndex) -> + table_get_row(T, RowIndex); +table_get_row([], _RowIndex) -> + no_such_row. + +table_get_next_row([Row | _T], []) -> + {ok, Row}; +table_get_next_row([Row | _T], [Index | _]) when element(1, Row) > Index -> + {ok, Row}; +table_get_next_row([_Row | T], RowIndex) -> + table_get_next_row(T, RowIndex); +table_get_next_row([], _RowIndex) -> + endOfTable. + +table_delete_row([{Index, _, _, _} | T], [Index]) -> + T; +table_delete_row([H | T], RowIndex) -> + [H | table_delete_row(T, RowIndex)]; +table_delete_row([], _RowIndex) -> + []. + +table_add_row([Row | T], NewRow) when element(1, Row) > element(1, NewRow) -> + [NewRow, Row | T]; +table_add_row([H | T], NewRow) -> + [H | table_add_row(T, NewRow)]; +table_add_row([], NewRow) -> + [NewRow]. + +make_row([Index], [{2, Name}, {3, Address} | _]) -> + {Index, Name, Address, ?active}. + +merge_rows(Row, [{Col, NewVal} | T]) -> + merge_rows(setelement(Col, Row, NewVal), T); +merge_rows(Row, []) -> + Row. + + diff --git a/lib/snmp/examples/ex2/Makefile b/lib/snmp/examples/ex2/Makefile new file mode 100644 index 0000000000..7fbd7f530b --- /dev/null +++ b/lib/snmp/examples/ex2/Makefile @@ -0,0 +1,93 @@ +#-*-makefile-*- ; force emacs to enter makefile-mode + +# %CopyrightBegin% +# +# Copyright Ericsson AB 2006-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) + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- + +ifneq ($(MIBS_VERBOSITY),) +SNMP_FLAGS += +'{verbosity,$(MIBS_VERBOSITY)}' +endif + +ERL_COMPILE_FLAGS += -pa $(ERL_TOP)/lib/snmp/ebin +ERL_COMPILE_FLAGS += -I../include \ + -Dversion=\"$(VSN)$(PRE_VSN)\" \ + +'{parse_transform,sys_pre_attributes}' \ + +'{attribute,insert,app_vsn,$(APP_VSN)}' \ + -I$(ERL_TOP)/lib/stdlib \ + $(SNMP_FLAGS) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/snmp-$(VSN) +EXAMPLE_RELSYSDIR = $(RELSYSDIR)/examples +EX2_RELSYSDIR = $(EXAMPLE_RELSYSDIR)/ex2 + +# ---------------------------------------------------- +# Common macros +# ---------------------------------------------------- + +MODULES = \ + snmp_ex2_manager \ + snmp_ex2_simple_standard_test + +ERL_FILES = $(MODULES:%=%.erl) + +TARGET_FILES= \ + $(ERL_FILES:%.erl=%.$(EMULATOR)) + + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +debug opt: build + +clean: + rm -f $(TARGET_FILES) + rm -f core *~ + +docs: + +build: $(TARGET_FILES) + + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + $(INSTALL_DIR) $(EXAMPLE_RELSYSDIR) + $(INSTALL_DIR) $(EX2_RELSYSDIR) + $(INSTALL_DATA) $(ERL_FILES) $(EX2_RELSYSDIR) + $(INSTALL_DATA) $(TARGET_FILES) $(EX2_RELSYSDIR) + +release_docs_spec: diff --git a/lib/snmp/examples/ex2/snmp_ex2_manager.erl b/lib/snmp/examples/ex2/snmp_ex2_manager.erl new file mode 100644 index 0000000000..79cfd94469 --- /dev/null +++ b/lib/snmp/examples/ex2/snmp_ex2_manager.erl @@ -0,0 +1,407 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-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 examplifies how to write test suites for your SNMP agent. +%%---------------------------------------------------------------------- + +-module(snmp_ex2_manager). + +-behaviour(gen_server). +-behaviour(snmpm_user). + +-export([start_link/0, start_link/1, stop/0, + agent/2, + sync_get/2, + sync_get_next/2, + sync_get_bulk/4, + sync_set/2, + + oid_to_name/1 + ]). + +%% 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]). + +-include_lib("snmp/include/snmp_types.hrl"). + + +-define(SERVER, ?MODULE). +-define(USER, ?MODULE). +-define(USER_MOD, ?MODULE). + +-record(state, {parent}). + + +%%%------------------------------------------------------------------- +%%% API +%%%------------------------------------------------------------------- + +start_link() -> + start_link([]). + +start_link(Opts) when is_list(Opts) -> + gen_server:start_link({local, ?SERVER}, ?MODULE, [self(), Opts], []). + +stop() -> + cast(stop). + + +%% --- Instruct manager to handle an agent --- + +agent(TargetName, Conf) -> + call({agent, TargetName, Conf}). + + +%% --- Various SNMP operations ---- + +sync_get(TargetName, Oids) -> + call({sync_get, TargetName, Oids}). + +sync_get_next(TargetName, Oids) -> + call({sync_get_next, TargetName, Oids}). + +sync_get_bulk(TargetName, NR, MR, Oids) -> + call({sync_get_bulk, TargetName, NR, MR, Oids}). + +sync_set(TargetName, VarsAndVals) -> + call({sync_set, TargetName, VarsAndVals}). + + +%% --- Misc utility functions --- + +oid_to_name(Oid) -> + call({oid_to_name, Oid}). + + +%%%------------------------------------------------------------------- +%%% Callback functions from gen_server +%%%------------------------------------------------------------------- + +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}; + Crap -> + {stop, Crap} + end. + +do_init(Opts) -> + {Dir, MgrConf, MgrOpts} = parse_opts(Opts), + write_config(Dir, MgrConf), + start_manager(MgrOpts), + register_user(), + {ok, #state{}}. + +write_config(Dir, Conf) -> + case snmp_config:write_manager_config(Dir, "", Conf) of + ok -> + ok; + Error -> + error({failed_writing_config, Error}) + end. + +start_manager(Opts) -> + case snmpm:start_link(Opts) of + ok -> + ok; + Error -> + error({failed_starting_manager, Error}) + end. + +register_user() -> + case snmpm:register_user(?USER, ?USER_MOD, self()) of + ok -> + ok; + Error -> + error({failed_register_user, Error}) + end. + +parse_opts(Opts) -> + Port = get_opt(port, Opts, 5000), + EngineId = get_opt(engine_id, Opts, "mgrEngine"), + MMS = get_opt(max_message_size, Opts, 484), + + MgrConf = [{port, Port}, + {engine_id, EngineId}, + {max_message_size, MMS}], + + %% Manager options + Mibs = get_opt(mibs, Opts, []), + Vsns = get_opt(versions, Opts, [v1, v2, v3]), + {ok, Cwd} = file:get_cwd(), + Dir = get_opt(dir, Opts, Cwd), + MgrOpts = [{mibs, Mibs}, + {versions, Vsns}, + %% {server, [{verbosity, trace}]}, + {config, [% {verbosity, trace}, + {dir, Dir}, {db_dir, Dir}]}], + + {Dir, MgrConf, MgrOpts}. + + +%%-------------------------------------------------------------------- +%% 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({agent, TargetName, Conf}, _From, S) -> + Reply = (catch snmpm:register_agent(?USER, TargetName, Conf)), + {reply, Reply, S}; + +handle_call({oid_to_name, Oid}, _From, S) -> + Reply = (catch snmpm:oid_to_name(Oid)), + {reply, Reply, S}; + +handle_call({sync_get, TargetName, Oids}, _From, S) -> + Reply = (catch snmpm:sync_get(?USER, TargetName, Oids)), + {reply, Reply, S}; + +handle_call({sync_get_next, TargetName, Oids}, _From, S) -> + Reply = (catch snmpm:sync_get_next(?USER, TargetName, Oids)), + {reply, Reply, S}; + +handle_call({sync_get_bulk, TargetName, NR, MR, Oids}, _From, S) -> + Reply = (catch snmpm:sync_get_bulk(?USER, TargetName, NR, MR, Oids)), + {reply, Reply, S}; + +handle_call({sync_set, TargetName, VarsAndVals}, _From, 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, Req}}, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_cast/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_cast(stop, S) -> + (catch snmpm:stop()), + {stop, normal, S}; + +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_callback, Tag, Info}, State) -> + handle_snmp_callback(Tag, 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}. + + +%% ======================================================================== +%% ======================================================================== + +handle_snmp_callback(handle_error, {ReqId, Reason}) -> + io:format("*** FAILURE ***" + "~n Request Id: ~p" + "~n Reason: ~p" + "~n", [ReqId, Reason]), + ok; +handle_snmp_callback(handle_agent, {Addr, Port, SnmpInfo}) -> + {ES, EI, VBs} = SnmpInfo, + io:format("*** UNKNOWN AGENT ***" + "~n Address: ~p" + "~n Port: ~p" + "~n SNMP Info: " + "~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [Addr, Port, ES, EI, VBs]), + ok; +handle_snmp_callback(handle_pdu, {TargetName, ReqId, SnmpResponse}) -> + {ES, EI, VBs} = SnmpResponse, + io:format("*** Received PDU ***" + "~n TargetName: ~p" + "~n Request Id: ~p" + "~n SNMP response:" + "~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [TargetName, ReqId, ES, EI, VBs]), + ok; +handle_snmp_callback(handle_trap, {TargetName, SnmpTrap}) -> + TrapStr = + case SnmpTrap of + {Enteprise, Generic, Spec, Timestamp, Varbinds} -> + io_lib:format("~n Generic: ~w" + "~n Exterprise: ~w" + "~n Specific: ~w" + "~n Timestamp: ~w" + "~n Varbinds: ~p", + [Generic, Enteprise, Spec, Timestamp, Varbinds]); + {ErrorStatus, ErrorIndex, Varbinds} -> + io_lib:format("~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [ErrorStatus, ErrorIndex, Varbinds]) + end, + io:format("*** Received TRAP ***" + "~n TargetName: ~p" + "~n SNMP trap: ~s" + "~n", [TargetName, lists:flatten(TrapStr)]), + ok; +handle_snmp_callback(handle_inform, {TargetName, SnmpInform}) -> + {ES, EI, VBs} = SnmpInform, + io:format("*** Received INFORM ***" + "~n TargetName: ~p" + "~n SNMP inform: " + "~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [TargetName, ES, EI, VBs]), + ok; +handle_snmp_callback(handle_report, {TargetName, SnmpReport}) -> + {ES, EI, VBs} = SnmpReport, + io:format("*** Received REPORT ***" + "~n TargetName: ~p" + "~n SNMP report: " + "~n Error Status: ~w" + "~n Error Index: ~w" + "~n Varbinds: ~p" + "~n", [TargetName, ES, EI, VBs]), + ok; +handle_snmp_callback(BadTag, Crap) -> + io:format("*** Received crap ***" + "~n ~p" + "~n ~p" + "~n", [BadTag, Crap]), + ok. + + + +error(Reason) -> + throw({error, Reason}). + + +error_msg(F, A) -> + catch error_logger:error_msg("*** TEST-MANAGER: " ++ F ++ "~n", A). + + +call(Req) -> + gen_server:call(?SERVER, Req, infinity). + +cast(Msg) -> + gen_server:cast(?SERVER, Msg). + + +%% ======================================================================== +%% Misc internal utility functions +%% ======================================================================== + +%% 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. + + +%% ======================================================================== +%% SNMPM user callback functions +%% ======================================================================== + +handle_error(ReqId, Reason, Server) when is_pid(Server) -> + report_callback(Server, handle_error, {ReqId, Reason}), + ignore. + + +handle_agent(Addr, Port, SnmpInfo, Server) when is_pid(Server) -> + report_callback(Server, handle_agent, {Addr, Port, SnmpInfo}), + ignore. + + +handle_pdu(TargetName, ReqId, SnmpResponse, Server) when is_pid(Server) -> + report_callback(Server, handle_pdu, {TargetName, ReqId, SnmpResponse}), + ignore. + + +handle_trap(TargetName, SnmpTrap, Server) when is_pid(Server) -> + report_callback(Server, handle_trap, {TargetName, SnmpTrap}), + ok. + +handle_inform(TargetName, SnmpInform, Server) when is_pid(Server) -> + report_callback(Server, handle_inform, {TargetName, SnmpInform}), + ok. + + +handle_report(TargetName, SnmpReport, Server) when is_pid(Server) -> + report_callback(Server, handle_inform, {TargetName, SnmpReport}), + ok. + +report_callback(Pid, Tag, Info) -> + Pid ! {snmp_callback, Tag, Info}. diff --git a/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl b/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl new file mode 100644 index 0000000000..16fe79d1a5 --- /dev/null +++ b/lib/snmp/examples/ex2/snmp_ex2_simple_standard_test.erl @@ -0,0 +1,287 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2006-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 examplifies how to write test suites for your SNMP agent. +%%---------------------------------------------------------------------- + +-module(snmp_ex2_simple_standard_test). + +-export([start/0, start/1, start/3]). + +-include_lib("snmp/include/snmp_types.hrl"). + +%% -define(USER, agent_tester). +%% -define(USER_MOD, ?MODULE). +%% -define(USER_MOD, snmpm_user_default). + +-record(command, {tag, desc, cmd, verify}). + +start() -> + {ok, Hostname} = inet:gethostname(), + {ok, Addr} = inet:getaddr(Hostname, inet), + start(Addr). + +start(Addr) -> + start([std_mib("STANDARD-MIB")], Addr, [{community, "public"}]). + +start(Mibs, AgentAddr, AgentConfig) -> + Conf = [{mibs, Mibs}], + {ok, _Pid} = snmp_ex2_manager:start_link(Conf), + snmp_ex2_manager:agent(AgentAddr, AgentConfig), + simple_standard_test(AgentAddr), + snmp_ex2_manager:stop(). + +simple_standard_test(AgentAddr) -> + Commands = + [ + #command{tag = 1, + desc = "get-next [1,1]", + cmd = fun() -> + gn(AgentAddr, [1,1]) + end, + verify = fun({ok, Res, _}) -> + verify_vbs(Res, + [{sysDescr, 'OCTET STRING'}]); + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end}, + #command{tag = 2, + desc = "get-next [1,3]", + cmd = fun() -> + gn(AgentAddr, [1,3]) + end, + verify = fun({ok, Res, _}) -> + verify_vbs(Res, + [{sysDescr, 'OCTET STRING'}]); + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end}, + #command{tag = 3, + desc = "get-next [1,3,6]", + cmd = fun() -> + gn(AgentAddr, [1,3,6]) + end, + verify = fun({ok, Res, _}) -> + verify_vbs(Res, + [{sysDescr, 'OCTET STRING'}]); + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end}, + #command{tag = 4, + desc = "get-next [1,3,6]", + cmd = fun() -> + gn(AgentAddr, [1,3,6,1]) + end, + verify = fun({ok, Res, _}) -> + verify_vbs(Res, + [{sysDescr, 'OCTET STRING'}]); + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end}, + #command{tag = 5, + desc = "get-next [1,3,6,1,2]", + cmd = fun() -> + gn(AgentAddr, [1,3,6]) + end, + verify = fun({ok, Res, _}) -> + verify_vbs(Res, + [{sysDescr, 'OCTET STRING'}]); + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end}, + #command{tag = 6, + desc = "get-next [1,3,6,1,2,1]", + cmd = fun() -> + gn(AgentAddr, [1,3,6]) + end, + verify = fun({ok, Res, _}) -> + verify_vbs(Res, + [{sysDescr, 'OCTET STRING'}]); + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end}, + #command{tag = 7, + desc = "get-next [1,3,6,1,2,1,1]", + cmd = fun() -> + gn(AgentAddr, [1,3,6]) + end, + verify = fun({ok, Res, _}) -> + verify_vbs(Res, + [{sysDescr, 'OCTET STRING'}]); + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end}, + #command{tag = 8, + desc = "get-next [1,3,6,1,2,1,1,1]", + cmd = fun() -> + gn(AgentAddr, [1,3,6]) + end, + verify = fun({ok, Res, _}) -> + verify_vbs(Res, + [{sysDescr, 'OCTET STRING'}]); + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end}, + #command{tag = 9, + desc = "get [sysDescr,0]", + cmd = fun() -> + g(AgentAddr, [sysDescr,0]) + end, + verify = fun({ok, Res, _}) -> + verify_vbs(Res, + [{sysDescr, 'OCTET STRING'}]); + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end}, + #command{tag = 10, + desc = "get [1,3,6,1,2,1,1,1]", + cmd = fun() -> + g(AgentAddr, [1,3,6,1,2,1,1,1]) + end, + verify = fun({ok, {noError, 0, [Vb]}, _}) -> + case Vb of + #varbind{oid = [1,3,6,1,2,1,1,1], + value = noSuchInstance} -> + {ok, + lists:flatten( + io_lib:format("~n noSuchInstance", []))}; + #varbind{oid = [1,3,6,1,2,1,1,1], + value = noSuchName} -> + {ok, + lists:flatten( + io_lib:format("~n noSuchName", + []))}; + _ -> + {error, {unexpected_vb, Vb}} + end; + ({error, Reason}) -> + {error, {command_failed, Reason}}; + (Crap) -> + {error, {unexpected_command_result, Crap}} + end} + ], + ok = commands(Commands), + io:format("Test completed.~n"). + + +commands([]) -> + ok; +commands([#command{tag = Tag, + desc = Desc, + cmd = Cmd, + verify = Verify}|Commands]) -> + io:format("Command ~2w (~s): ", [Tag, Desc]), + case Verify((catch Cmd())) of + {ok, Val} -> + io:format("ok~s~n", [Val]), + ok; + {error, Reason} -> + io:format("error" + "~n ~p" + "~n", [Reason]) + end, + commands(Commands). + + +%% --- Command shorts --- + +gn(Addr, [H|_] = Oids) when is_list(H) -> + snmp_ex2_manager:sync_get_next(Addr, Oids); +gn(Addr, Oid) -> + gn(Addr, [Oid]). + +g(Addr, [H|_] = Oids) when is_list(H) -> + snmp_ex2_manager:sync_get(Addr, Oids); +g(Addr, Oid) -> + g(Addr, [Oid]). + + +%% Verify that all varbinds have the expected name and type +verify_vbs({noError, 0, Vbs}, NameAndTypes) -> + (catch verify_vbs(Vbs, NameAndTypes, "")); +verify_vbs(Res, _) -> + {error, {unexpected_result, Res}}. + +verify_vbs([], _, Acc) -> + {ok, Acc}; +verify_vbs([Vb|T], NameAndTypes, Acc) -> + Val = verify_vb(Vb, NameAndTypes), + Acc2 = lists:flatten(io_lib:format("~s~n ~s", [Acc, Val])), + verify_vbs(T, NameAndTypes, Acc2). + +verify_vb(#varbind{oid = Oid, variabletype = Type, value = Val} = Vb, + NameAndTypes) -> + case lists:reverse(Oid) of + [0|RevOid] -> + case snmp_ex2_manager:oid_to_name(lists:reverse(RevOid)) of + {ok, Name} -> + case lists:keysearch(Name, 1, NameAndTypes) of + {value, {Name, Type}} -> + Val; + {value, {Name, WrongType}} -> + error({wrong_type, {WrongType, Vb}}); + false -> + error({unexpected_name, {Name, Vb}}) + end; + {error, Reason} -> + error({unexpected_oid, {Reason, Vb}}) + end; + _ -> + case lists:keysearch(Oid, 1, NameAndTypes) of + {value, {Oid, Type}} -> + Val; + {value, {Oid, WrongType}} -> + error({wrong_type, {WrongType, Vb}}); + false -> + error({unexpected_oid, Vb}) + end + end. + + +std_mib(MibName) -> + j(std_dir(), MibName). + +std_dir() -> j(code:priv_dir(snmp), "mibs"). + +j(Dir, Filename) -> + filename:join(Dir, Filename). + + +error(Reason) -> + throw({error, Reason}). + + diff --git a/lib/snmp/examples/mcli/.gitignore b/lib/snmp/examples/mcli/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/snmp/examples/mcli/.gitignore diff --git a/lib/snmp/examples/subdirs.mk b/lib/snmp/examples/subdirs.mk new file mode 100644 index 0000000000..9f4b69951e --- /dev/null +++ b/lib/snmp/examples/subdirs.mk @@ -0,0 +1,21 @@ +#-*-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% + +SUB_DIRECTORIES = ex1 ex2 + |