From 6d5ac23e0b5aca3b27d9922e7f7448d6117b7aa4 Mon Sep 17 00:00:00 2001
From: Micael Karlberg Register the manager entity (=user) responsible for specific
- agent(s).
port() = integer() > 0
-pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | 'set-request' | trap | 'get-bulk-request' | 'inform-request' | report
+pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
+ 'set-request' | trap | 'get-bulk-request' | 'inform-request' |
+ report
The argument
The argument
The type of
DATA TYPES
port() = integer() > 0
-pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | 'set-request' | trap | 'get-bulk-request' | 'inform-request' | report | trappdu
+pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |
+ 'set-request' | trap | 'get-bulk-request' | 'inform-request' |
+ report | trappdu
--
cgit v1.2.3
From df8e3029f933bbbdb3c20edfd26d37ec6722d7ae Mon Sep 17 00:00:00 2001
From: Micael Karlberg
Date: Tue, 10 Jul 2012 16:45:43 +0200
Subject: Fixed problem with TimeTicks decode
The decoder had a problem with data of type TimeTicks.
Also, the handling of invalid values (value out of range)
was bad for both TimeTicks and Unsigned32.
OTP-10132
---
lib/snmp/doc/src/notes.xml | 48 +++++++++++
lib/snmp/src/app/snmp.appup.src | 43 ++++++++++
lib/snmp/src/misc/snmp_pdus.erl | 100 ++++++++++++++--------
lib/snmp/test/snmp_pdus_test.erl | 176 +++++++++++++++++++++++++++++++--------
lib/snmp/vsn.mk | 2 +-
5 files changed, 297 insertions(+), 72 deletions(-)
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 2d045faa0f..097238af9a 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -33,6 +33,54 @@
+
+ SNMP Development Toolkit 4.22.1
+ Version 4.22.1 supports code replacement in runtime from/to
+ version 4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21.
+
+
+ Improvements and new features
+ -
+
+
+
+
+
+
+ Fixed Bugs and Malfunctions
+
+
+
+ -
+
Incorrect TimeTicks decode. Also bad handling of
+ invalid encode (value outside of value range) for both
+ TimeTicks and Unsigned32.
+ Own Id: OTP-10132
+
+
+
+
+
+
+
+ Incompatibilities
+ -
+
+
+
+
+
SNMP Development Toolkit 4.22
Version 4.22 supports code replacement in runtime from/to
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 8360d88c94..bfffd5810c 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -22,8 +22,15 @@
%% ----- U p g r a d e -------------------------------------------------------
[
+ {"4.22",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []}
+ ]
+ },
{"4.21.7",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -50,6 +57,8 @@
},
{"4.21.6",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -76,6 +85,8 @@
},
{"4.21.5",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -107,6 +118,8 @@
},
{"4.21.4",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -141,6 +154,8 @@
},
{"4.21.3",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -175,6 +190,8 @@
},
{"4.21.2",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -211,6 +228,8 @@
},
{"4.21.1",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -248,6 +267,8 @@
},
{"4.21",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -288,8 +309,16 @@
%% ------D o w n g r a d e ---------------------------------------------------
[
+ {"4.22",
+ [
+ {load_module, snmp_pdus, soft_purge, soft_purge, []}
+ ]
+ },
{"4.21.7",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -316,6 +345,8 @@
},
{"4.21.6",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -342,6 +373,8 @@
},
{"4.21.5",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -373,6 +406,8 @@
},
{"4.21.4",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -407,6 +442,8 @@
},
{"4.21.3",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -441,6 +478,8 @@
},
{"4.21.2",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -477,6 +516,8 @@
},
{"4.21.1",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
@@ -514,6 +555,8 @@
},
{"4.21",
[
+ {load_module, snmp_pdus, soft_purge, soft_purge, []},
+
{load_module, snmp_config, soft_purge, soft_purge, []},
{load_module, snmp_conf, soft_purge, soft_purge, []},
{load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]},
diff --git a/lib/snmp/src/misc/snmp_pdus.erl b/lib/snmp/src/misc/snmp_pdus.erl
index 0788d86b2d..e15be4a298 100644
--- a/lib/snmp/src/misc/snmp_pdus.erl
+++ b/lib/snmp/src/misc/snmp_pdus.erl
@@ -254,68 +254,87 @@ strip(0, _Tail) ->
%%----------------------------------------------------------------------
%% Returns:{Type, Value}
%%----------------------------------------------------------------------
+
+%% OBJECT IDENTIFIER
dec_value([6 | Bytes]) ->
{Value, Rest} = dec_oid_notag(Bytes),
{{'OBJECT IDENTIFIER', Value}, Rest};
dec_value([5,0 | T]) ->
{{'NULL', 'NULL'}, T};
+
+%% INTEGER
dec_value([2 | Bytes]) ->
{Value, Rest} = dec_integer_notag(Bytes),
{{'INTEGER', Value}, Rest};
+
+%% OCTET STRING
dec_value([4 | Bytes]) ->
{Value, Rest} = dec_oct_str_notag(Bytes),
{{'OCTET STRING', Value}, Rest};
+
+%% IpAddress
dec_value([64 | Bytes]) ->
{Value, Rest} = dec_oct_str_notag(Bytes),
{{'IpAddress', Value}, Rest};
+
+%% Counter32
dec_value([65 | Bytes]) ->
%% Counter32 is an unsigned 32 but is actually encoded as
%% a signed integer 32 (INTEGER).
{Value, Rest} = dec_integer_notag(Bytes),
Value2 =
- if
- (Value >= 0) andalso (Value =< 16#ffffffff) ->
- %% We accept value above 16#7fffffff
- %% in order to be backward bug-compatible
- Value;
- (Value < 0) ->
- 16#ffffffff + Value + 1;
- true ->
- exit({error, {bad_counter32, Value}})
- end,
+ if
+ (Value >= 0) andalso (Value =< 16#ffffffff) ->
+ %% We accept value above 16#7fffffff
+ %% in order to be backward bug-compatible
+ Value;
+ (Value < 0) ->
+ 16#ffffffff + Value + 1;
+ true ->
+ exit({error, {bad_counter32, Value}})
+ end,
{{'Counter32', Value2}, Rest};
+
+%% Unsigned32
dec_value([66 | Bytes]) ->
{Value, Rest} = dec_integer_notag(Bytes),
if
- (Value >= 0) andalso (Value =< 4294967295) ->
- {{'Unsigned32', Value}, Rest};
- true ->
- exit({error, {bad_unsigned32, Value}})
+ (Value >= 0) andalso (Value =< 16#ffffffff) ->
+ {{'Unsigned32', Value}, Rest};
+ true ->
+ exit({error, {bad_unsigned32, Value}})
end;
+
+%% TimeTicks
dec_value([67 | Bytes]) ->
{Value, Rest} = dec_integer_notag(Bytes),
- if
- (Value >= 0) andalso (Value =< 4294967295) ->
+ if
+ (Value >= 0) andalso (Value =< 16#ffffffff) ->
{{'TimeTicks', Value}, Rest};
true ->
exit({error, {bad_timeticks, Value}})
end;
+
+%% Opaque
dec_value([68 | Bytes]) ->
{Value, Rest} = dec_oct_str_notag(Bytes),
{{'Opaque', Value}, Rest};
+
+%% Counter64
dec_value([70 | Bytes]) ->
%% Counter64 is an unsigned 64 but is actually encoded as
%% a signed integer 64.
{Value, Rest} = dec_integer_notag(Bytes),
Value2 =
- if
- (Value >= 0) andalso (Value < 16#8000000000000000) ->
- Value;
- (Value < 0) ->
- 18446744073709551615 + Value + 1;
- true ->
- exit({error, {bad_counter64, Value}}) end,
+ if
+ (Value >= 0) andalso (Value < 16#8000000000000000) ->
+ Value;
+ (Value < 0) ->
+ 16#ffffffffffffffff + Value + 1;
+ true ->
+ exit({error, {bad_counter64, Value}}) end,
{{'Counter64', Value2}, Rest};
+
dec_value([128,0|T]) ->
{{'NULL', noSuchObject}, T};
dec_value([129,0|T]) ->
@@ -629,7 +648,7 @@ enc_VarBind_attributes(#varbind{oid = Oid, variabletype = Type,value = Val}) ->
ValueBytes = enc_value(Type, Val),
lists:append(OidBytes, ValueBytes).
-enc_value('INTEGER',Val) ->
+enc_value('INTEGER', Val) ->
enc_integer_tag(Val);
enc_value('OCTET STRING', Val) ->
enc_oct_str_tag(Val);
@@ -637,7 +656,7 @@ enc_value('BITS', Val) ->
enc_oct_str_tag(bits_to_str(Val));
enc_value('OBJECT IDENTIFIER', Val) ->
enc_oid_tag(Val);
-enc_value('IpAddress',Val) ->
+enc_value('IpAddress', Val) ->
Bytes2 = enc_oct_str_notag(Val),
Len2 = elength(length(Bytes2)),
lists:append([64 | Len2],Bytes2);
@@ -668,6 +687,24 @@ enc_value('Counter32', Val) ->
Bytes2 = enc_integer_notag(Val2),
Len2 = elength(length(Bytes2)),
lists:append([65 | Len2],Bytes2);
+enc_value('Unsigned32', Val) ->
+ if
+ (Val >= 0) andalso (Val =< 4294967295) ->
+ Bytes2 = enc_integer_notag(Val),
+ Len2 = elength(length(Bytes2)),
+ lists:append([66 | Len2], Bytes2);
+ true ->
+ exit({error, {bad_counter32, Val}})
+ end;
+enc_value('TimeTicks', Val) ->
+ if
+ (Val >= 0) andalso (Val =< 4294967295) ->
+ Bytes2 = enc_integer_notag(Val),
+ Len2 = elength(length(Bytes2)),
+ lists:append([67 | Len2], Bytes2);
+ true ->
+ exit({error, {bad_timeticks, Val}})
+ end;
enc_value('Counter64', Val) ->
Val2 =
if
@@ -682,18 +719,7 @@ enc_value('Counter64', Val) ->
end,
Bytes2 = enc_integer_notag(Val2),
Len2 = elength(length(Bytes2)),
- lists:append([70 | Len2],Bytes2);
-enc_value(Type, Val) ->
- Bytes2 = enc_integer_notag(Val),
- Len2 = elength(length(Bytes2)),
- lists:append([enc_val_tag(Type,Val) | Len2],Bytes2).
-
-enc_val_tag('Counter32',Val) when (Val >= 0) andalso (Val =< 4294967295) ->
- 65;
-enc_val_tag('Unsigned32', Val) when (Val >= 0) andalso (Val =< 4294967295) ->
- 66;
-enc_val_tag('TimeTicks', Val) when (Val >= 0) andalso (Val =< 4294967295) ->
- 67.
+ lists:append([70 | Len2],Bytes2).
%%----------------------------------------------------------------------
diff --git a/lib/snmp/test/snmp_pdus_test.erl b/lib/snmp/test/snmp_pdus_test.erl
index 07b6d6b657..0d78749bcb 100644
--- a/lib/snmp/test/snmp_pdus_test.erl
+++ b/lib/snmp/test/snmp_pdus_test.erl
@@ -39,6 +39,7 @@
otp7575/1,
otp8563/1,
otp9022/1,
+ otp10132/1,
init_per_testcase/2, end_per_testcase/2
]).
@@ -74,16 +75,16 @@ end_per_testcase(_Case, Config) when is_list(Config) ->
%% Test case definitions
%%======================================================================
all() ->
-[{group, tickets}].
+ [{group, tickets}].
groups() ->
- [{tickets, [], [otp7575, otp8563, otp9022]}].
+ [{tickets, [], [otp7575, otp8563, otp9022, otp10132]}].
init_per_group(_GroupName, Config) ->
- Config.
+ Config.
end_per_group(_GroupName, Config) ->
- Config.
+ Config.
@@ -94,7 +95,7 @@ end_per_group(_GroupName, Config) ->
%%======================================================================
otp7575(suite) -> [];
-otp7575(doc) -> ["OTP-7575"];
+otp7575(doc) -> ["OTP-7575 - Message version"];
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>>,
@@ -127,48 +128,55 @@ otp7575(Config) when is_list(Config) ->
otp8563(suite) -> [];
-otp8563(doc) -> ["OTP-8563"];
+otp8563(doc) -> ["OTP-8563 - Counter64"];
otp8563(Config) when is_list(Config) ->
Val1 = 16#7fffffffffffffff,
- io:format("try encode and decode ~w~n", [Val1]),
+ io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]),
Enc1 = snmp_pdus:enc_value('Counter64', Val1),
+ io:format(" => ~w~n", [Enc1]),
{{'Counter64', Val1}, []} = snmp_pdus:dec_value(Enc1),
Val2 = Val1 + 1,
- io:format("try encode and decode ~w~n", [Val2]),
+ io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]),
Enc2 = snmp_pdus:enc_value('Counter64', Val2),
+ io:format(" => ~w~n", [Enc2]),
{{'Counter64', Val2}, []} = snmp_pdus:dec_value(Enc2),
Val3 = Val2 + 1,
- io:format("try encode and decode ~w~n", [Val3]),
+ io:format("try encode and decode valule 3: ~w (0x~.16b)~n", [Val3, Val3]),
Enc3 = snmp_pdus:enc_value('Counter64', Val3),
+ io:format(" => ~w~n", [Enc3]),
{{'Counter64', Val3}, []} = snmp_pdus:dec_value(Enc3),
Val4 = 16#fffffffffffffffe,
- io:format("try encode and decode ~w~n", [Val4]),
+ io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]),
Enc4 = snmp_pdus:enc_value('Counter64', Val4),
+ io:format(" => ~w~n", [Enc4]),
{{'Counter64', Val4}, []} = snmp_pdus:dec_value(Enc4),
Val5 = Val4 + 1,
- io:format("try encode and decode ~w~n", [Val5]),
+ io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]),
Enc5 = snmp_pdus:enc_value('Counter64', Val5),
+ io:format(" => ~w~n", [Enc5]),
{{'Counter64', Val5}, []} = snmp_pdus:dec_value(Enc5),
Val6 = 16#ffffffffffffffff + 1,
- io:format("try and fail to encode ~w~n", [Val6]),
+ io:format("try and fail to encode value 6: ~w (0x~.16b)~n", [Val6, Val6]),
case (catch snmp_pdus:enc_value('Counter64', Val6)) of
{'EXIT', {error, {bad_counter64, Val6}}} ->
ok;
Unexpected6 ->
+ io:format(" => ~w~n", [Unexpected6]),
exit({unexpected_encode_result, Unexpected6, Val6})
end,
Val7 = -1,
- io:format("try and fail to encode ~w~n", [Val7]),
+ io:format("try and fail to encode value 7: ~w~n", [Val7]),
case (catch snmp_pdus:enc_value('Counter64', Val7)) of
{'EXIT', {error, {bad_counter64, Val7}}} ->
ok;
Unexpected7 ->
+ io:format(" => ~w~n", [Unexpected7]),
exit({unexpected_encode_result, Unexpected7, Val7})
end,
@@ -176,51 +184,151 @@ otp8563(Config) when is_list(Config) ->
otp9022(suite) -> [];
-otp9022(doc) -> ["OTP-9022"];
+otp9022(doc) -> ["OTP-9022 - Counter32"];
otp9022(Config) when is_list(Config) ->
- Val1 = 16#7fffffff,
- io:format("try encode and decode ~w~n", [Val1]),
+ Val0 = 2908389204,
+ io:format("try encode and decode value 0: ~w (0x~.16b)~n", [Val0, Val0]),
+ Enc0 = snmp_pdus:enc_value('Counter32', Val0),
+ io:format(" => ~w~n", [Enc0]),
+ {{'Counter32', Val0}, []} = snmp_pdus:dec_value(Enc0),
+
+ Val1 = 0,
+ io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]),
Enc1 = snmp_pdus:enc_value('Counter32', Val1),
+ io:format(" => ~w~n", [Enc1]),
{{'Counter32', Val1}, []} = snmp_pdus:dec_value(Enc1),
Val2 = Val1 + 1,
- io:format("try encode and decode ~w~n", [Val2]),
+ io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]),
Enc2 = snmp_pdus:enc_value('Counter32', Val2),
+ io:format(" => ~w~n", [Enc2]),
{{'Counter32', Val2}, []} = snmp_pdus:dec_value(Enc2),
- Val3 = Val2 + 1,
- io:format("try encode and decode ~w~n", [Val3]),
+ Val3 = 16#7ffffffe,
+ io:format("try encode and decode value 3: ~w (0x~.16b)~n", [Val3, Val3]),
Enc3 = snmp_pdus:enc_value('Counter32', Val3),
+ io:format(" => ~w~n", [Enc3]),
{{'Counter32', Val3}, []} = snmp_pdus:dec_value(Enc3),
- Val4 = 16#fffffffe,
- io:format("try encode and decode ~w~n", [Val4]),
+ Val4 = Val3 + 1,
+ io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]),
Enc4 = snmp_pdus:enc_value('Counter32', Val4),
+ io:format(" => ~w~n", [Enc4]),
{{'Counter32', Val4}, []} = snmp_pdus:dec_value(Enc4),
Val5 = Val4 + 1,
- io:format("try encode and decode ~w~n", [Val5]),
+ io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]),
Enc5 = snmp_pdus:enc_value('Counter32', Val5),
+ io:format(" => ~w~n", [Enc5]),
{{'Counter32', Val5}, []} = snmp_pdus:dec_value(Enc5),
- Val6 = 16#ffffffff + 1,
- io:format("try and fail to encode ~w~n", [Val6]),
- case (catch snmp_pdus:enc_value('Counter32', Val6)) of
- {'EXIT', {error, {bad_counter32, Val6}}} ->
+ Val6 = 16#fffffffe,
+ io:format("try encode and decode value 6: ~w (0x~.16b)~n", [Val6, Val6]),
+ Enc6 = snmp_pdus:enc_value('Counter32', Val6),
+ io:format(" => ~w~n", [Enc6]),
+ {{'Counter32', Val6}, []} = snmp_pdus:dec_value(Enc6),
+
+ Val7 = Val6 + 1,
+ io:format("try encode and decode value 7: ~w (0x~.16b)~n", [Val7, Val7]),
+ Enc7 = snmp_pdus:enc_value('Counter32', Val7),
+ io:format(" => ~w~n", [Enc7]),
+ {{'Counter32', Val7}, []} = snmp_pdus:dec_value(Enc7),
+
+ Val8 = 16#ffffffff + 1,
+ io:format("try and fail to encode value 8: ~w (0x~.16b)~n", [Val8, Val8]),
+ case (catch snmp_pdus:enc_value('Counter32', Val8)) of
+ {'EXIT', {error, {bad_counter32, Val8}}} ->
ok;
- Unexpected6 ->
- exit({unexpected_encode_result, Unexpected6, Val6})
+ Unexpected8 ->
+ io:format(" => ~w~n", [Unexpected8]),
+ exit({unexpected_encode_result, Unexpected8, Val8})
end,
- Val7 = -1,
- io:format("try and fail to encode ~w~n", [Val7]),
- case (catch snmp_pdus:enc_value('Counter32', Val7)) of
- {'EXIT', {error, {bad_counter32, Val7}}} ->
+ Val9 = -1,
+ io:format("try and fail to encode value 9: ~w~n", [Val9]),
+ case (catch snmp_pdus:enc_value('Counter32', Val9)) of
+ {'EXIT', {error, {bad_counter32, Val9}}} ->
ok;
- Unexpected7 ->
- exit({unexpected_encode_result, Unexpected7, Val7})
+ Unexpected9 ->
+ io:format(" => ~w~n", [Unexpected9]),
+ exit({unexpected_encode_result, Unexpected9, Val9})
+ end,
+
+ ok.
+
+
+otp10132(suite) -> [];
+otp10132(doc) -> ["OTP-10132 - TimeTicks"];
+otp10132(Config) when is_list(Config) ->
+ Val0 = 2159001034,
+ io:format("try encode and decode value 0: ~w (0x~.16b)~n", [Val0, Val0]),
+ Enc0 = snmp_pdus:enc_value('TimeTicks', Val0),
+ io:format(" => ~w~n", [Enc0]),
+ {{'TimeTicks', Val0}, []} = snmp_pdus:dec_value(Enc0),
+
+ Val1 = 0,
+ io:format("try encode and decode value 1: ~w (0x~.16b)~n", [Val1, Val1]),
+ Enc1 = snmp_pdus:enc_value('TimeTicks', Val1),
+ io:format(" => ~w~n", [Enc1]),
+ {{'TimeTicks', Val1}, []} = snmp_pdus:dec_value(Enc1),
+
+ Val2 = Val1 + 1,
+ io:format("try encode and decode value 2: ~w (0x~.16b)~n", [Val2, Val2]),
+ Enc2 = snmp_pdus:enc_value('TimeTicks', Val2),
+ io:format(" => ~w~n", [Enc2]),
+ {{'TimeTicks', Val2}, []} = snmp_pdus:dec_value(Enc2),
+
+ Val3 = 16#7ffffffe,
+ io:format("try encode and decode value 3: ~w (0x~.16b)~n", [Val3, Val3]),
+ Enc3 = snmp_pdus:enc_value('TimeTicks', Val3),
+ io:format(" => ~w~n", [Enc3]),
+ {{'TimeTicks', Val3}, []} = snmp_pdus:dec_value(Enc3),
+
+ Val4 = Val3 + 1,
+ io:format("try encode and decode value 4: ~w (0x~.16b)~n", [Val4, Val4]),
+ Enc4 = snmp_pdus:enc_value('TimeTicks', Val4),
+ io:format(" => ~w~n", [Enc4]),
+ {{'TimeTicks', Val4}, []} = snmp_pdus:dec_value(Enc4),
+
+ Val5 = Val4 + 1,
+ io:format("try encode and decode value 5: ~w (0x~.16b)~n", [Val5, Val5]),
+ Enc5 = snmp_pdus:enc_value('TimeTicks', Val5),
+ io:format(" => ~w~n", [Enc5]),
+ {{'TimeTicks', Val5}, []} = snmp_pdus:dec_value(Enc5),
+
+ Val6 = 16#fffffffe,
+ io:format("try encode and decode value 6: ~w (0x~.16b)~n", [Val6, Val6]),
+ Enc6 = snmp_pdus:enc_value('TimeTicks', Val6),
+ io:format(" => ~w~n", [Enc6]),
+ {{'TimeTicks', Val6}, []} = snmp_pdus:dec_value(Enc6),
+
+ Val7 = Val6 + 1,
+ io:format("try encode and decode value 7: ~w (0x~.16b)~n", [Val7, Val7]),
+ Enc7 = snmp_pdus:enc_value('TimeTicks', Val7),
+ io:format(" => ~w~n", [Enc7]),
+ {{'TimeTicks', Val7}, []} = snmp_pdus:dec_value(Enc7),
+
+ Val8 = Val7 + 1,
+ io:format("try and fail to encode value 8: ~w (0x~.16b)~n", [Val8, Val8]),
+ case (catch snmp_pdus:enc_value('TimeTicks', Val8)) of
+ {'EXIT', {error, {bad_timeticks, Val8}}} ->
+ ok;
+ Unexpected8 ->
+ io:format(" => ~w~n", [Unexpected8]),
+ exit({unexpected_encode_result, Unexpected8, Val8})
end,
+ Val9 = -1,
+ io:format("try and fail to encode value 9: ~w~n", [Val9]),
+ case (catch snmp_pdus:enc_value('TimeTicks', Val9)) of
+ {'EXIT', {error, {bad_timeticks, Val9}}} ->
+ ok;
+ Unexpected9 ->
+ io:format(" => ~w~n", [Unexpected9]),
+ exit({unexpected_encode_result, Unexpected9, Val9})
+ end,
+
+ io:format("done~n", []),
ok.
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index 36b9764bc8..b90dbe4eef 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 4.22
+SNMP_VSN = 4.22.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
--
cgit v1.2.3
From 9b5b085ddb5ee649a7fc518ad534d513c68ad699 Mon Sep 17 00:00:00 2001
From: Stefan Zegenhagen
Date: Tue, 31 Jul 2012 10:38:49 +0200
Subject: [snmp/agent] Errors in vacmAccessTable RowStatus handling
There are problems with the handling of vacmAccessTableStatus that cause
some SNMP test suites to report errors.
Most notably, errorneous set operations frequently cause "genErr" errors
to be returned which usually is a sign for bad coding. These "genErr"
errors are usually caused by badmatch exceptions coming from
{ok, Row} = snmpa_vacm:get_row(RowIndex)
if the row does not exist.
This patch fixes the badmatch errors and adjusts the semantic of the
RowStatus handling in that table to be compliant with the RowStatus
textual description of SNPMv2-TC MIB.
---
lib/snmp/src/agent/snmp_view_based_acm_mib.erl | 121 ++++++++++++++++---------
1 file changed, 79 insertions(+), 42 deletions(-)
diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
index 479a44795f..71dcc0f849 100644
--- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
+++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
@@ -565,48 +565,85 @@ vacmAccessTable(is_set_ok, RowIndex, Cols0) ->
case (catch verify_vacmAccessTable_cols(Cols0, [])) of
{ok, Cols} ->
IsValidKey = is_valid_key(RowIndex),
- case lists:keysearch(?vacmAccessStatus, 1, Cols) of
- %% Ok, if contextMatch is init
- {value, {Col, ?'RowStatus_active'}} ->
- {ok, Row} = snmpa_vacm:get_row(RowIndex),
- case element(?vacmAContextMatch, Row) of
- noinit -> {inconsistentValue, Col};
- _ -> {noError, 0}
- end;
- {value, {Col, ?'RowStatus_notInService'}} -> % Ok, if not notReady
- {ok, Row} = snmpa_vacm:get_row(RowIndex),
- case element(?vacmAStatus, Row) of
- ?'RowStatus_notReady' -> {inconsistentValue, Col};
- _ -> {noError, 0}
- end;
- {value, {Col, ?'RowStatus_notReady'}} -> % never ok!
- {inconsistentValue, Col};
- {value, {Col, ?'RowStatus_createAndGo'}} -> % ok, if it doesn't exist
- Res = lists:keysearch(?vacmAccessContextMatch, 1, Cols),
- case snmpa_vacm:get_row(RowIndex) of
- false when (IsValidKey =:= true) andalso
- is_tuple(Res) -> {noError, 0};
- false -> {noCreation, Col}; % Bad RowIndex
- _ -> {inconsistentValue, Col}
- end;
- {value, {Col, ?'RowStatus_createAndWait'}} -> % ok, if it doesn't exist
- case snmpa_vacm:get_row(RowIndex) of
- false when (IsValidKey =:= true) -> {noError, 0};
- false -> {noCreation, Col}; % Bad RowIndex
- _ -> {inconsistentValue, Col}
- end;
- {value, {_Col, ?'RowStatus_destroy'}} -> % always ok!
- {noError, 0};
- _ -> % otherwise, it's a change; it must exist
- case snmpa_vacm:get_row(RowIndex) of
- {ok, _} ->
- {noError, 0};
- false ->
- {inconsistentName, element(1, hd(Cols))}
- end
- end;
- Error ->
- Error
+ StatusCol = lists:keyfind(?vacmAccessStatus, 1, Cols),
+ OldRow = snmpa_vacm:get_row(RowIndex),
+ case {StatusCol, OldRow} of
+ {{Col, ?'RowStatus_active'}, false} ->
+ % row does not yet exist => inconsistentValue
+ % (see SNMPv2-TC.mib, RowStatus textual convention)
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_active'}, {ok, Row}} ->
+ %% Ok, if contextMatch is init
+ case element(?vacmAContextMatch, Row) of
+ noinit ->
+ % check whether ContextMatch is being set in the same operation
+ case proplists:get_value(?vacmAccessContextMatch, Cols) of
+ undefined ->
+ % no, we can't make this row active yet
+ {inconsistentValue, Col};
+ _ ->
+ % ok, activate the row
+ {noError, 0}
+ end;
+ _ ->
+ {noError, 0}
+ end;
+ {{Col, ?'RowStatus_notInService'}, false} ->
+ % row does not yet exist => inconsistentValue
+ % (see SNMPv2-TC.mib, RowStatus textual convention)
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_notInService'}, {ok, Row}} ->
+ % Ok, if not notReady
+ case element(?vacmAStatus, Row) of
+ ?'RowStatus_notReady' ->
+ {inconsistentValue, Col};
+ _ ->
+ {noError, 0}
+ end;
+ {{Col, ?'RowStatus_notReady'}, _} ->
+ % never ok!
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_createAndGo'}, false} ->
+ % ok, if it doesn't exist
+ Res = lists:keysearch(?vacmAccessContextMatch, 1, Cols),
+ if
+ IsValidKey /= true ->
+ % bad RowIndex => noCreation
+ {noCreation, Col};
+ is_tuple(Res) ->
+ % required field is present => noError
+ {noError, 0};
+ true ->
+ % required field is missing => inconsistentValue
+ {inconsistentValue, Col}
+ end;
+ {{Col, ?'RowStatus_createAndGo'}, _} ->
+ % row already exists => inconsistentValue
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_createAndWait'}, false} ->
+ % ok, if it doesn't exist
+ if
+ IsValidKey =:= true ->
+ % RowIndex is valid => noError
+ {noError, 0};
+ true ->
+ {noCreation, Col}
+ end;
+ {{Col, ?'RowStatus_createAndWait'}, _} ->
+ % Row already exists => inconsistentValue
+ {inconsistentValue, Col};
+ {value, {_Col, ?'RowStatus_destroy'}} ->
+ % always ok!
+ {noError, 0};
+ {_, false} ->
+ % otherwise, it's a row change; row does not exist => inconsistentName
+ {inconsistentName, element(1, hd(Cols))};
+ _ ->
+ % row change and row exists => noError
+ {noError, 0}
+ end;
+ Error ->
+ Error
end;
vacmAccessTable(set, RowIndex, Cols0) ->
case (catch verify_vacmAccessTable_cols(Cols0, [])) of
--
cgit v1.2.3
From 730ef404d96a9db21e92101409cf9043b2126848 Mon Sep 17 00:00:00 2001
From: Micael Karlberg
Date: Wed, 1 Aug 2012 10:20:16 +0200
Subject: [snmp] Add release notes, appup instruction and proper version
---
lib/snmp/doc/src/notes.xml | 60 +++++++++++++++++++++++++++++++++++++++++
lib/snmp/src/app/snmp.appup.src | 10 +++++++
lib/snmp/vsn.mk | 2 +-
3 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 2d045faa0f..4ec254971b 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -33,6 +33,66 @@
+
+ SNMP Development Toolkit 4.22.1
+ Version 4.22.1 supports code replacement in runtime from/to
+ version 4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21.
+
+
+ Improvements and new features
+
+
+
+ -
+
[agent] Errors in vacmAccessTable RowStatus handling.
+ There are problems with the handling of vacmAccessTableStatus
+ that cause some SNMP test suites to report errors.
+ Most notably, erroneous set operations frequently cause "genErr"
+ errors to be returned. These "genErr" errors are usually caused
+ by badmatch exceptions coming from
+ {ok, Row} = snmpa_vacm:get_row(RowIndex)
+ if the row does not exist.
+ The semantics of the RowStatus handling in that table has
+ been adjusted to be compliant with the RowStatus
+ textual description of SNPMv2-TC MIB.
+ Stefan Zegenhagen
+ Own Id: OTP-10164
+
+
+
+
+
+
+ Fixed Bugs and Malfunctions
+ -
+
+
+
+
+
+
+ Incompatibilities
+ -
+
+
+
+
+
SNMP Development Toolkit 4.22
Version 4.22 supports code replacement in runtime from/to
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 8360d88c94..54c07bed26 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -22,6 +22,11 @@
%% ----- U p g r a d e -------------------------------------------------------
[
+ {"4.22",
+ [
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}
+ ]
+ },
{"4.21.7",
[
{load_module, snmp_config, soft_purge, soft_purge, []},
@@ -288,6 +293,11 @@
%% ------D o w n g r a d e ---------------------------------------------------
[
+ {"4.22",
+ [
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}
+ ]
+ },
{"4.21.7",
[
{load_module, snmp_config, soft_purge, soft_purge, []},
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index 36b9764bc8..b90dbe4eef 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 4.22
+SNMP_VSN = 4.22.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
--
cgit v1.2.3
From 6c3ce92734fe80bec370857a83ccf375c3f20565 Mon Sep 17 00:00:00 2001
From: Micael Karlberg
Date: Wed, 1 Aug 2012 10:28:50 +0200
Subject: [snmp/agent] Cleanup
---
lib/snmp/src/agent/snmp_view_based_acm_mib.erl | 161 +++++++++++++------------
1 file changed, 82 insertions(+), 79 deletions(-)
diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
index 71dcc0f849..e7dea52857 100644
--- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
+++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
@@ -565,85 +565,88 @@ vacmAccessTable(is_set_ok, RowIndex, Cols0) ->
case (catch verify_vacmAccessTable_cols(Cols0, [])) of
{ok, Cols} ->
IsValidKey = is_valid_key(RowIndex),
- StatusCol = lists:keyfind(?vacmAccessStatus, 1, Cols),
- OldRow = snmpa_vacm:get_row(RowIndex),
- case {StatusCol, OldRow} of
- {{Col, ?'RowStatus_active'}, false} ->
- % row does not yet exist => inconsistentValue
- % (see SNMPv2-TC.mib, RowStatus textual convention)
- {inconsistentValue, Col};
- {{Col, ?'RowStatus_active'}, {ok, Row}} ->
- %% Ok, if contextMatch is init
- case element(?vacmAContextMatch, Row) of
- noinit ->
- % check whether ContextMatch is being set in the same operation
- case proplists:get_value(?vacmAccessContextMatch, Cols) of
- undefined ->
- % no, we can't make this row active yet
- {inconsistentValue, Col};
- _ ->
- % ok, activate the row
- {noError, 0}
- end;
- _ ->
- {noError, 0}
- end;
- {{Col, ?'RowStatus_notInService'}, false} ->
- % row does not yet exist => inconsistentValue
- % (see SNMPv2-TC.mib, RowStatus textual convention)
- {inconsistentValue, Col};
- {{Col, ?'RowStatus_notInService'}, {ok, Row}} ->
- % Ok, if not notReady
- case element(?vacmAStatus, Row) of
- ?'RowStatus_notReady' ->
- {inconsistentValue, Col};
- _ ->
- {noError, 0}
- end;
- {{Col, ?'RowStatus_notReady'}, _} ->
- % never ok!
- {inconsistentValue, Col};
- {{Col, ?'RowStatus_createAndGo'}, false} ->
- % ok, if it doesn't exist
- Res = lists:keysearch(?vacmAccessContextMatch, 1, Cols),
- if
- IsValidKey /= true ->
- % bad RowIndex => noCreation
- {noCreation, Col};
- is_tuple(Res) ->
- % required field is present => noError
- {noError, 0};
- true ->
- % required field is missing => inconsistentValue
- {inconsistentValue, Col}
- end;
- {{Col, ?'RowStatus_createAndGo'}, _} ->
- % row already exists => inconsistentValue
- {inconsistentValue, Col};
- {{Col, ?'RowStatus_createAndWait'}, false} ->
- % ok, if it doesn't exist
- if
- IsValidKey =:= true ->
- % RowIndex is valid => noError
- {noError, 0};
- true ->
- {noCreation, Col}
- end;
- {{Col, ?'RowStatus_createAndWait'}, _} ->
- % Row already exists => inconsistentValue
- {inconsistentValue, Col};
- {value, {_Col, ?'RowStatus_destroy'}} ->
- % always ok!
- {noError, 0};
- {_, false} ->
- % otherwise, it's a row change; row does not exist => inconsistentName
- {inconsistentName, element(1, hd(Cols))};
- _ ->
- % row change and row exists => noError
- {noError, 0}
- end;
- Error ->
- Error
+ StatusCol = lists:keyfind(?vacmAccessStatus, 1, Cols),
+ MaybeRow = snmpa_vacm:get_row(RowIndex),
+ case {StatusCol, MaybeRow} of
+ {{Col, ?'RowStatus_active'}, false} ->
+ %% row does not yet exist => inconsistentValue
+ %% (see SNMPv2-TC.mib, RowStatus textual convention)
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_active'}, {ok, Row}} ->
+ %% Ok, if contextMatch is init
+ case element(?vacmAContextMatch, Row) of
+ noinit ->
+ %% check whether ContextMatch is being set in
+ %% the same operation
+ case proplists:get_value(?vacmAccessContextMatch,
+ Cols) of
+ undefined ->
+ %% no, we can't make this row active yet
+ {inconsistentValue, Col};
+ _ ->
+ %% ok, activate the row
+ {noError, 0}
+ end;
+ _ ->
+ {noError, 0}
+ end;
+ {{Col, ?'RowStatus_notInService'}, false} ->
+ %% row does not yet exist => inconsistentValue
+ %% (see SNMPv2-TC.mib, RowStatus textual convention)
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_notInService'}, {ok, Row}} ->
+ %% Ok, if not notReady
+ case element(?vacmAStatus, Row) of
+ ?'RowStatus_notReady' ->
+ {inconsistentValue, Col};
+ _ ->
+ {noError, 0}
+ end;
+ {{Col, ?'RowStatus_notReady'}, _} ->
+ %% never ok!
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_createAndGo'}, false} ->
+ %% ok, if it doesn't exist
+ Res = lists:keysearch(?vacmAccessContextMatch, 1, Cols),
+ if
+ IsValidKey =/= true ->
+ %% bad RowIndex => noCreation
+ {noCreation, Col};
+ is_tuple(Res) ->
+ %% required field is present => noError
+ {noError, 0};
+ true ->
+ %% required field is missing => inconsistentValue
+ {inconsistentValue, Col}
+ end;
+ {{Col, ?'RowStatus_createAndGo'}, _} ->
+ %% row already exists => inconsistentValue
+ {inconsistentValue, Col};
+ {{Col, ?'RowStatus_createAndWait'}, false} ->
+ %% ok, if it doesn't exist
+ if
+ IsValidKey =:= true ->
+ %% RowIndex is valid => noError
+ {noError, 0};
+ true ->
+ {noCreation, Col}
+ end;
+ {{Col, ?'RowStatus_createAndWait'}, _} ->
+ %% Row already exists => inconsistentValue
+ {inconsistentValue, Col};
+ {value, {_Col, ?'RowStatus_destroy'}} ->
+ %% always ok!
+ {noError, 0};
+ {_, false} ->
+ %% otherwise, it's a row change;
+ %% row does not exist => inconsistentName
+ {inconsistentName, element(1, hd(Cols))};
+ _ ->
+ %% row change and row exists => noError
+ {noError, 0}
+ end;
+ Error ->
+ Error
end;
vacmAccessTable(set, RowIndex, Cols0) ->
case (catch verify_vacmAccessTable_cols(Cols0, [])) of
--
cgit v1.2.3
From 2df3ddfbc2cd99c21b8a125858ab0090a318295e Mon Sep 17 00:00:00 2001
From: Micael Karlberg
Date: Wed, 1 Aug 2012 11:32:57 +0200
Subject: [snmp] Add proper version, release notes and appup instruction
---
lib/snmp/doc/src/notes.xml | 49 +++++++++++++++++++++++++++++++++++++++++
lib/snmp/src/app/snmp.appup.src | 10 +++++++++
lib/snmp/vsn.mk | 2 +-
3 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 2d045faa0f..84a249020a 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -33,6 +33,55 @@
+
+ SNMP Development Toolkit 4.22.1
+ Version 4.22.1 supports code replacement in runtime from/to
+ version 4.22, 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and
+ 4.21.
+
+
+ Improvements and new features
+ -
+
+
+
+
+
+
+ Fixed Bugs and Malfunctions
+
+
+
+ -
+
[manager]
+ snmpm:log_to_io/6
+ did not use the LogName argument.
+ Own Id: OTP-10066
+
+
+
+
+
+
+
+ Incompatibilities
+ -
+
+
+
+
+
SNMP Development Toolkit 4.22
Version 4.22 supports code replacement in runtime from/to
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 8360d88c94..f34aeddbb9 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -22,6 +22,11 @@
%% ----- U p g r a d e -------------------------------------------------------
[
+ {"4.22",
+ [
+ {load_module, snmpm, soft_purge, soft_purge, []}
+ ]
+ },
{"4.21.7",
[
{load_module, snmp_config, soft_purge, soft_purge, []},
@@ -288,6 +293,11 @@
%% ------D o w n g r a d e ---------------------------------------------------
[
+ {"4.22",
+ [
+ {load_module, snmpm, soft_purge, soft_purge, []}
+ ]
+ },
{"4.21.7",
[
{load_module, snmp_config, soft_purge, soft_purge, []},
diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk
index 36b9764bc8..b90dbe4eef 100644
--- a/lib/snmp/vsn.mk
+++ b/lib/snmp/vsn.mk
@@ -18,6 +18,6 @@
# %CopyrightEnd%
APPLICATION = snmp
-SNMP_VSN = 4.22
+SNMP_VSN = 4.22.1
PRE_VSN =
APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)"
--
cgit v1.2.3
From b83743233210ccb1f294346be93a6cd03b58683e Mon Sep 17 00:00:00 2001
From: Micael Karlberg
Date: Sat, 21 Jul 2012 20:09:37 +0200
Subject: [snmp/agent] Add agent info printout at begin and end of test case
Add agent info ( snmpa:info() ) in the init_per_testcase
and end_per_testcase in the agent test suite.
Also display (print) the audit trail log in the end_per_testcase.
---
lib/snmp/test/snmp_agent_test.erl | 45 ++++++++++++++++++++++++---------------
1 file changed, 28 insertions(+), 17 deletions(-)
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index 8ee5dd534d..736e1c8ebd 100644
--- a/lib/snmp/test/snmp_agent_test.erl
+++ b/lib/snmp/test/snmp_agent_test.erl
@@ -346,47 +346,61 @@ end_per_group(_GroupName, Config) ->
-init_per_testcase(otp8395 = Case, Config) when is_list(Config) ->
+init_per_testcase(Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
+ "~n Agant Info: ~p", [snmpa:info()]),
+ init_per_testcase1(Case, Config).
+
+init_per_testcase1(otp8395 = Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> entry with"
"~n Case: ~p"
"~n Config: ~p", [Case, Config]),
otp8395({init, init_per_testcase2(Case, Config)});
-init_per_testcase(otp9884 = Case, Config) when is_list(Config) ->
- ?DBG("init_per_testcase -> entry with"
+init_per_testcase1(otp9884 = Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> entry with"
"~n Case: ~p"
"~n Config: ~p", [Case, Config]),
otp9884({init, init_per_testcase2(Case, Config)});
-init_per_testcase(otp_7157_test = _Case, Config) when is_list(Config) ->
- ?DBG("init_per_testcase -> entry with"
+init_per_testcase1(otp_7157_test = _Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> 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"
+init_per_testcase1(v2_inform_i = _Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> 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"
+init_per_testcase1(v3_inform_i = _Case, Config) when is_list(Config) ->
+ ?DBG("init_per_testcase1 -> 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) ->
+init_per_testcase1(_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 ].
-end_per_testcase(otp8395, Config) when is_list(Config) ->
+end_per_testcase(Case, Config) when is_list(Config) ->
+ ?DBG("end_per_testcase -> entry with"
+ "~n Agant Info: ~p", [snmpa:info()]),
+
+ p("Display log"),
+ display_log(Config),
+
+ end_per_testcase1(Case, Config).
+
+end_per_testcase1(otp8395, Config) when is_list(Config) ->
otp8395({fin, Config});
-end_per_testcase(otp9884, Config) when is_list(Config) ->
+end_per_testcase1(otp9884, Config) when is_list(Config) ->
otp9884({fin, Config});
-end_per_testcase(_Case, Config) when is_list(Config) ->
- ?DBG("end_per_testcase -> entry with"
+end_per_testcase1(_Case, Config) when is_list(Config) ->
+ ?DBG("end_per_testcase1 -> entry with"
"~n Case: ~p"
"~n Config: ~p", [_Case, Config]),
Dog = ?config(watchdog, Config),
@@ -1406,9 +1420,6 @@ simple(Config) when is_list(Config) ->
try_test(simple_standard_test),
- p("Display log"),
- display_log(Config),
-
p("done"),
ok.
--
cgit v1.2.3
From b8970a3899e2cb62e6a1c3a053afdef7ffca9542 Mon Sep 17 00:00:00 2001
From: Micael Karlberg
Date: Sun, 22 Jul 2012 08:11:30 +0200
Subject: [snmp/agent] Printout (of agent info) using plain print function
Printout (of agent info) using plain print function
rather than debug (DBG) macro.
---
lib/snmp/test/snmp_agent_test.erl | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl
index 736e1c8ebd..e1d7f33b3f 100644
--- a/lib/snmp/test/snmp_agent_test.erl
+++ b/lib/snmp/test/snmp_agent_test.erl
@@ -346,9 +346,15 @@ end_per_group(_GroupName, Config) ->
+%% ---- Init Per TestCase ----
+
init_per_testcase(Case, Config) when is_list(Config) ->
?DBG("init_per_testcase -> entry with"
- "~n Agant Info: ~p", [snmpa:info()]),
+ "~n Config: ~p", [Config]),
+
+ p("Agent Info: "
+ "~n ~p", [snmpa:info()]),
+
init_per_testcase1(Case, Config).
init_per_testcase1(otp8395 = Case, Config) when is_list(Config) ->
@@ -386,11 +392,16 @@ init_per_testcase1(_Case, Config) when is_list(Config) ->
Dog = ?WD_START(?MINS(6)),
[{watchdog, Dog}| Config ].
+
+%% ---- End Per TestCase ----
+
end_per_testcase(Case, Config) when is_list(Config) ->
?DBG("end_per_testcase -> entry with"
- "~n Agant Info: ~p", [snmpa:info()]),
+ "~n Config: ~p", [Config]),
+
+ p("Agent Info: "
+ "~n ~p", [snmpa:info()]),
- p("Display log"),
display_log(Config),
end_per_testcase1(Case, Config).
--
cgit v1.2.3
From e20215f00ee5c442736269995cf147468406d796 Mon Sep 17 00:00:00 2001
From: Stefan Zegenhagen
Date: Tue, 31 Jul 2012 15:10:05 +0200
Subject: [snmp/agent] Fix walk over vacmAccessTable
The get_next implementation of vacmAccessTable did not return all
available table data. Instead, it only returned the first column for
each row, and all columns for the last row available.
Fix the get_next implementation of vacmAccessTable to return all table
entries.
---
lib/snmp/src/agent/snmp_view_based_acm_mib.erl | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
index e7dea52857..436f15eb9c 100644
--- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
+++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl
@@ -774,10 +774,15 @@ do_vacmAccessTable_set(RowIndex, Cols) ->
%% Cols are sorted, and all columns are > 3.
+do_get_next(_RowIndex, []) ->
+ % Cols can be empty because we're called for each
+ % output of split_cols(); and one of that may well
+ % be empty.
+ [];
do_get_next(RowIndex, Cols) ->
case snmpa_vacm:get_next_row(RowIndex) of
{NextIndex, Row} ->
- F1 = fun(Col) when Col < ?vacmAccessStatus ->
+ F1 = fun(Col) when Col =< ?vacmAccessStatus ->
{[Col | NextIndex], element(Col-3, Row)};
(_) ->
endOfTable
@@ -785,9 +790,9 @@ do_get_next(RowIndex, Cols) ->
lists:map(F1, Cols);
false ->
case snmpa_vacm:get_next_row([]) of
- {_NextIndex, Row} ->
+ {NextIndex2, Row} ->
F2 = fun(Col) when Col < ?vacmAccessStatus ->
- {[Col+1 | RowIndex], element(Col-2, Row)};
+ {[Col+1 | NextIndex2], element(Col-2, Row)};
(_) ->
endOfTable
end,
--
cgit v1.2.3
From feae72c93a4cdebb4287d0b52f165b638b159cb2 Mon Sep 17 00:00:00 2001
From: Micael Karlberg
Date: Thu, 2 Aug 2012 08:42:39 +0200
Subject: [snmp] Updated release notes
---
lib/snmp/doc/src/notes.xml | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index ea5648b808..80871c56fc 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -72,6 +72,17 @@
-->
+ -
+
[agent] Fix walk over vacmAccessTable.
+ Fix the get_next implementation of vacmAccessTable to
+ return all table entries.
+ The get_next implementation of vacmAccessTable did not return
+ all available table data. Instead, it only returned the first
+ column for each row, and all columns for the last row available.
+ Stefan Zegenhagen
+ Own Id: OTP-10165
+
+
-
[manager]
snmpm:log_to_io/6
--
cgit v1.2.3
From d43fdb09477c6781c67557399e05988dd7895556 Mon Sep 17 00:00:00 2001
From: Stefan Zegenhagen
Date: Mon, 23 Jul 2012 16:16:58 +0200
Subject: [snmp/agent] Semantic fixes to SNMP-USER-BASED-SM_MIB
The semantics allow the usmUserAuthKeyChange and usmUserPrivKeyChange
objects to be written to in the same set requests that also creates and
clones the user. This was not possible beforehand, causing test tools
checking semantic SNMPv3 behaviour to fail on a lot of test cases.
Furthermore, once the user has been cloned by writing to an instance of
usmUserCloneFrom, further set-operations to the same object will not
return an error, but be no-ops. Especially, it must be avoided to copy
security parameters again (possibly even from a different user).
---
lib/snmp/src/agent/snmp_user_based_sm_mib.erl | 153 ++++++++++++++------------
1 file changed, 82 insertions(+), 71 deletions(-)
diff --git a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
index 2e801622e7..9d67e336af 100644
--- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
+++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
@@ -54,6 +54,7 @@
%% Columns not accessible via SNMP
-define(usmUserAuthKey, 14).
-define(usmUserPrivKey, 15).
+-define(is_cloning, 16).
%%%-----------------------------------------------------------------
@@ -564,7 +565,9 @@ usmUserTable(set, RowIndex, Cols0) ->
{ok, Cols} ->
?vtrace("usmUserTable(set) -> verified"
"~n Cols: ~p", [Cols]),
- NCols = pre_set(RowIndex, Cols),
+ % check whether we're cloning. if so, get cloned params and add a few
+ % defaults that might be needed.
+ NCols = pre_set(RowIndex, validate_clone_from(RowIndex, Cols)),
?vtrace("usmUserTable(set) -> pre-set: "
"~n NCols: ~p", [NCols]),
%% NOTE: The NCols parameter is sent to snmp_generic, but not to
@@ -730,30 +733,40 @@ validate_is_set_ok(Error, _RowIndex, _Cols) ->
Error.
do_validate_is_set_ok(RowIndex, Cols) ->
- validate_clone_from(RowIndex, Cols),
- validate_auth_protocol(RowIndex, Cols),
- validate_auth_key_change(RowIndex, Cols),
- validate_own_auth_key_change(RowIndex, Cols),
- validate_priv_protocol(RowIndex, Cols),
- validate_priv_key_change(RowIndex, Cols),
- validate_own_priv_key_change(RowIndex, Cols),
+ NCols = validate_clone_from(RowIndex, Cols),
+ validate_auth_protocol(RowIndex, NCols),
+ validate_auth_key_change(RowIndex, NCols),
+ validate_own_auth_key_change(RowIndex, NCols),
+ validate_priv_protocol(RowIndex, NCols),
+ validate_priv_key_change(RowIndex, NCols),
+ validate_own_priv_key_change(RowIndex, NCols),
ok.
pre_set(RowIndex, Cols) ->
+ %% Remove the ?is_cloning member again; it must no longer be
+ %% present.
+ Cols0 = lists:keydelete(?is_cloning, 1, Cols),
%% Possibly initialize the usmUserSecurityName and privacy keys
case snmp_generic:table_row_exists(db(usmUserTable), RowIndex) of
- true -> Cols;
+ true -> Cols0;
false ->
SecName = get_user_name(RowIndex),
- [{?usmUserSecurityName, SecName} | Cols] ++
- [{?usmUserAuthKey, ""},
- {?usmUserPrivKey, ""}]
+ Cols1 = [{?usmUserSecurityName, SecName} | Cols0],
+ case proplists:get_value(?is_cloning, Cols) of
+ true ->
+ % the row is just being cloned. the cloned user's
+ % passwords are already present in Cols and must
+ % not be overwritten.
+ Cols1;
+ _ ->
+ Cols1 ++ [{?usmUserAuthKey, ""},
+ {?usmUserPrivKey, ""}]
+ end
end.
validate_set({noError, 0}, RowIndex, Cols) ->
%% Now, all is_set_ok validation steps have been executed. So
%% everything is ready for the set.
- set_clone_from(RowIndex, Cols),
set_auth_key_change(RowIndex, Cols),
set_own_auth_key_change(RowIndex, Cols),
set_priv_key_change(RowIndex, Cols),
@@ -778,35 +791,63 @@ validate_clone_from(RowIndex, Cols) ->
case OldCloneFrom of
{value, Val} when Val /= noinit ->
%% This means that the cloning is already done...
- ok;
+ no_cloning(Cols);
_ ->
- %% Otherwise, we must check the CloneFrom value
- case snmp_generic:table_get_element(db(usmUserTable),
- RowIndex2,
- ?usmUserStatus) of
- {value, ?'RowStatus_active'} -> ok;
- _ -> inconsistentName(?usmUserCloneFrom)
- end
+ %% Otherwise, we must check the CloneFrom value. It
+ %% must relate to a usmUserEntry that exists and is active.
+ case snmp_generic:table_get_row(db(usmUserTable), RowIndex2) of
+ CloneFromRow when is_tuple(CloneFromRow) ->
+ case element(?usmUserStatus, CloneFromRow) of
+ ?'RowStatus_active' ->
+ get_cloned_cols(CloneFromRow, Cols);
+ _ ->
+ inconsistentName(?usmUserCloneFrom)
+ end;
+ undefined ->
+ inconsistentName(?usmUserCloneFrom)
+ end
end;
false ->
- ok
+ % no ?usmUserCloneFrom specified, don't modify columns
+ no_cloning(Cols)
end.
+get_cloned_cols(CloneFromRow, Cols) ->
+ % initialize cloned columns with data from CloneFromRow
+ % and overwrite that again with data found in Cols
+ AuthP = element(?usmUserAuthProtocol, CloneFromRow),
+ PrivP = element(?usmUserPrivProtocol, CloneFromRow),
+ AuthK = element(?usmUserAuthKey, CloneFromRow),
+ PrivK = element(?usmUserPrivKey, CloneFromRow),
+ ClonedCols = [{?usmUserAuthProtocol, AuthP},
+ {?usmUserPrivProtocol, PrivP},
+ {?usmUserAuthKey, AuthK},
+ {?usmUserPrivKey, PrivK},
+ {?is_cloning, true}
+ ],
+ Func = fun({Col, _} = Item, NCols) ->
+ lists:keystore(Col, 1, NCols, Item)
+ end,
+ Cols1 = lists:foldl(Func, ClonedCols, Cols),
+ lists:keysort(1, Cols1).
+
+no_cloning(Cols0) ->
+ Cols1 = lists:keydelete(?usmUserCloneFrom, Cols0),
+ lists:keydelete(?is_cloning, Cols1).
+
validate_auth_protocol(RowIndex, Cols) ->
case lists:keysearch(?usmUserAuthProtocol, 1, Cols) of
{value, {_Col, AuthProtocol}} ->
- %% Check if the row has been cloned; we can't check the
+ %% Check if the row is being cloned; we can't check the
%% old value of authProtocol, because if the row was
%% createAndWaited, the default value would have been
%% written (usmNoAuthProtocol).
- OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable),
- RowIndex,
- ?usmUserCloneFrom),
- case OldCloneFrom of
- {value, Val} when Val /= noinit ->
- %% This means that the cloning is already done; set is ok
- %% if new protocol is usmNoAuthProtocol
+ IsCloning = proplists:get_value(?is_cloning, Cols, false),
+ if
+ not IsCloning ->
+ %% This means that the row is not being cloned right
+ %% now; set is ok if new protocol is usmNoAuthProtocol
case AuthProtocol of
?usmNoAuthProtocol ->
%% Check that the Priv protocl is noPriv
@@ -821,7 +862,7 @@ validate_auth_protocol(RowIndex, Cols) ->
_ ->
wrongValue(?usmUserAuthProtocol)
end;
- _ ->
+ true ->
%% Otherwise, check that the new protocol is known,
%% and that the system we're running supports the
%% hash function.
@@ -897,10 +938,7 @@ validate_key_change(RowIndex, Cols, KeyChangeCol, Type) ->
OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable),
RowIndex,
?usmUserCloneFrom),
- IsClonePresent = case lists:keysearch(?usmUserCloneFrom, 1, Cols) of
- {value, _} -> true;
- false -> false
- end,
+ IsClonePresent = proplists:get_value(?is_cloning, Cols, false),
%% Set is ok if 1) the user already is created, 2) this is
%% a new user, which has been cloned, or is about to be
%% cloned.
@@ -912,7 +950,7 @@ validate_key_change(RowIndex, Cols, KeyChangeCol, Type) ->
%% The user is cloned in this operation
ok;
_ ->
- %% The user doen't exist, or hasn't been cloned,
+ %% The user doesn't exist, or hasn't been cloned,
%% and is not cloned in this operation.
inconsistentName(KeyChangeCol)
end,
@@ -945,11 +983,9 @@ validate_priv_protocol(RowIndex, Cols) ->
%% old value of privhProtocol, because if the row was
%% createAndWaited, the default value would have been
%% written (usmNoPrivProtocol).
- OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable),
- RowIndex,
- ?usmUserCloneFrom),
- case OldCloneFrom of
- {value, Val} when Val /= noinit ->
+ IsCloning = proplists:get_value(?is_cloning, Cols, false),
+ if
+ not IsCloning ->
%% This means that the cloning is already done; set is ok
%% if new protocol is usmNoPrivProtocol
case PrivProtocol of
@@ -962,7 +998,7 @@ validate_priv_protocol(RowIndex, Cols) ->
_ ->
wrongValue(?usmUserPrivProtocol)
end;
- _ ->
+ true ->
%% Otherwise, check that the new protocol is known,
%% and that the system we're running supports the
%% crypto function.
@@ -1005,31 +1041,6 @@ validate_priv_protocol(RowIndex, Cols) ->
end.
-set_clone_from(RowIndex, Cols) ->
- %% If CloneFrom is modified, do the cloning.
- case lists:keysearch(?usmUserCloneFrom, 1, Cols) of
- {value, {_Col, RowPointer}} ->
- RowIndex2 = extract_row(RowPointer), % won't fail
- CloneRow = snmp_generic:table_get_row(db(usmUserTable), RowIndex2,
- foi(usmUserTable)),
- AuthP = element(?usmUserAuthProtocol, CloneRow),
- PrivP = element(?usmUserPrivProtocol, CloneRow),
- AuthK = element(?usmUserAuthKey, CloneRow),
- PrivK = element(?usmUserPrivKey, CloneRow),
- SCols = [{?usmUserAuthProtocol, AuthP},
- {?usmUserPrivProtocol, PrivP},
- {?usmUserAuthKey, AuthK},
- {?usmUserPrivKey, PrivK}],
- case snmp_generic:table_set_elements(db(usmUserTable),
- RowIndex,
- SCols) of
- true -> ok;
- false -> {commitFailed, ?usmUserCloneFrom}
- end;
- false ->
- ok
- end.
-
set_auth_key_change(RowIndex, Cols) ->
set_key_change(RowIndex, Cols, ?usmUserAuthKeyChange, auth).
@@ -1071,9 +1082,9 @@ extract_row([H | T], [H | T2]) -> extract_row(T, T2);
extract_row([], [?usmUserSecurityName | T]) -> T;
extract_row(_, _) -> wrongValue(?usmUserCloneFrom).
-%% Pre: the user exixt
+%% Pre: the user exists or is being cloned in this operation
get_auth_proto(RowIndex, Cols) ->
- %% The protocol can be chanegd by the request too, otherwise,
+ %% The protocol can be changed by the request too, otherwise,
%% check the stored protocol.
case lists:keysearch(?usmUserAuthProtocol, 1, Cols) of
{value, {_, Protocol}} ->
@@ -1090,9 +1101,9 @@ get_auth_proto(RowIndex, Cols) ->
end
end.
-%% Pre: the user exixt
+%% Pre: the user exists or is being cloned in this operation
get_priv_proto(RowIndex, Cols) ->
- %% The protocol can be chanegd by the request too, otherwise,
+ %% The protocol can be changed by the request too, otherwise,
%% check the stored protocol.
case lists:keysearch(?usmUserPrivProtocol, 1, Cols) of
{value, {_, Protocol}} ->
--
cgit v1.2.3
From 12d50ad491c6800ab769662afac9a4b221c84648 Mon Sep 17 00:00:00 2001
From: Micael Karlberg
Date: Thu, 2 Aug 2012 10:16:28 +0200
Subject: [snmp] Update release notes and add appup instructions
---
lib/snmp/doc/src/notes.xml | 18 +++++++++++++++++-
lib/snmp/src/app/snmp.appup.src | 6 ++++--
2 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml
index 80871c56fc..442837d57d 100644
--- a/lib/snmp/doc/src/notes.xml
+++ b/lib/snmp/doc/src/notes.xml
@@ -47,7 +47,23 @@
-
-
[agent] Errors in vacmAccessTable RowStatus handling.
+
[agent] Sematic fixes to SNMP-USER-BASED-SM-MIB.
+ The semantics allow the usmUserAuthKeyChange and
+ usmUserPrivKeyChange objects to be written to in the
+ same set requests that also creates and clones the user.
+ This was not possible beforehand, causing test tools checking
+ semantic SNMPv3 behaviour to fail on a lot of test cases.
+ Furthermore, once the user has been cloned by writing to an
+ instance of usmUserCloneFrom , further set-operations to
+ the same object will not return an error, but be no-ops.
+ Especially, it must be avoided to copy security parameters
+ again (possibly even from a different user).
+ Stefan Zegenhagen
+ Own Id: OTP-10166
+
+
+ -
+
[agent] Errors in vacmAccessTable RowStatus handling.
There are problems with the handling of vacmAccessTableStatus
that cause some SNMP test suites to report errors.
Most notably, erroneous set operations frequently cause "genErr"
diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src
index 3991cdbce8..573ba8d0f5 100644
--- a/lib/snmp/src/app/snmp.appup.src
+++ b/lib/snmp/src/app/snmp.appup.src
@@ -26,7 +26,8 @@
[
{load_module, snmpm, soft_purge, soft_purge, []},
{load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []}
]
},
{"4.21.7",
@@ -315,7 +316,8 @@
[
{load_module, snmpm, soft_purge, soft_purge, []},
{load_module, snmp_pdus, soft_purge, soft_purge, []},
- {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}
+ {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []},
+ {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, []}
]
},
{"4.21.7",
--
cgit v1.2.3
From 96ca0eb1e6836ed0e6be0ba93f765c359ac17c27 Mon Sep 17 00:00:00 2001
From: Micael Karlberg
Date: Thu, 2 Aug 2012 10:40:11 +0200
Subject: [snmp/agent] Cleanup
lists:keydelete/2 does not exist (used in no_cloning)!
Introduced some simple wrapper functions for list
access (ke1delete, key1search, key1store and key1sort).
---
lib/snmp/src/agent/snmp_user_based_sm_mib.erl | 47 +++++++++++++++++++--------
1 file changed, 34 insertions(+), 13 deletions(-)
diff --git a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
index 9d67e336af..3c4ba1af66 100644
--- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
+++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl
@@ -745,7 +745,7 @@ do_validate_is_set_ok(RowIndex, Cols) ->
pre_set(RowIndex, Cols) ->
%% Remove the ?is_cloning member again; it must no longer be
%% present.
- Cols0 = lists:keydelete(?is_cloning, 1, Cols),
+ Cols0 = key1delete(?is_cloning, Cols),
%% Possibly initialize the usmUserSecurityName and privacy keys
case snmp_generic:table_row_exists(db(usmUserTable), RowIndex) of
true -> Cols0;
@@ -782,7 +782,7 @@ validate_set(Error, _RowIndex, _Cols) ->
%% no further checks.
%%-----------------------------------------------------------------
validate_clone_from(RowIndex, Cols) ->
- case lists:keysearch(?usmUserCloneFrom, 1, Cols) of
+ case key1search(?usmUserCloneFrom, Cols) of
{value, {_Col, RowPointer}} ->
RowIndex2 = extract_row(RowPointer),
OldCloneFrom = snmp_generic:table_get_element(db(usmUserTable),
@@ -826,18 +826,18 @@ get_cloned_cols(CloneFromRow, Cols) ->
{?is_cloning, true}
],
Func = fun({Col, _} = Item, NCols) ->
- lists:keystore(Col, 1, NCols, Item)
+ key1store(Col, NCols, Item)
end,
Cols1 = lists:foldl(Func, ClonedCols, Cols),
- lists:keysort(1, Cols1).
+ key1sort(Cols1).
no_cloning(Cols0) ->
- Cols1 = lists:keydelete(?usmUserCloneFrom, Cols0),
- lists:keydelete(?is_cloning, Cols1).
+ Cols1 = key1delete(?usmUserCloneFrom, Cols0),
+ key1delete(?is_cloning, Cols1).
validate_auth_protocol(RowIndex, Cols) ->
- case lists:keysearch(?usmUserAuthProtocol, 1, Cols) of
+ case key1search(?usmUserAuthProtocol, Cols) of
{value, {_Col, AuthProtocol}} ->
%% Check if the row is being cloned; we can't check the
%% old value of authProtocol, because if the row was
@@ -908,7 +908,7 @@ validate_own_priv_key_change(RowIndex, Cols) ->
%% Check that the requesting user is the same as the modified user
validate_requester(RowIndex, Cols, KeyChangeCol) ->
- case lists:keysearch(KeyChangeCol, 1, Cols) of
+ case key1search(KeyChangeCol, Cols) of
{value, _} ->
case get(sec_model) of % Check the securityModel in the request
?SEC_USM -> ok;
@@ -931,7 +931,7 @@ validate_requester(RowIndex, Cols, KeyChangeCol) ->
end.
validate_key_change(RowIndex, Cols, KeyChangeCol, Type) ->
- case lists:keysearch(KeyChangeCol, 1, Cols) of
+ case key1search(KeyChangeCol, Cols) of
{value, {_Col, KeyC}} ->
%% Check if the row has been cloned; or if it is cloned in
%% this set-operation.
@@ -977,7 +977,7 @@ validate_key_change(RowIndex, Cols, KeyChangeCol, Type) ->
end.
validate_priv_protocol(RowIndex, Cols) ->
- case lists:keysearch(?usmUserPrivProtocol, 1, Cols) of
+ case key1search(?usmUserPrivProtocol, Cols) of
{value, {_Col, PrivProtocol}} ->
%% Check if the row has been cloned; we can't check the
%% old value of privhProtocol, because if the row was
@@ -1054,7 +1054,7 @@ set_own_priv_key_change(RowIndex, Cols) ->
set_key_change(RowIndex, Cols, ?usmUserOwnPrivKeyChange, priv).
set_key_change(RowIndex, Cols, KeyChangeCol, Type) ->
- case lists:keysearch(KeyChangeCol, 1, Cols) of
+ case key1search(KeyChangeCol, Cols) of
{value, {_Col, KeyChange}} ->
KeyCol = case Type of
auth -> ?usmUserAuthKey;
@@ -1086,7 +1086,7 @@ extract_row(_, _) -> wrongValue(?usmUserCloneFrom).
get_auth_proto(RowIndex, Cols) ->
%% The protocol can be changed by the request too, otherwise,
%% check the stored protocol.
- case lists:keysearch(?usmUserAuthProtocol, 1, Cols) of
+ case key1search(?usmUserAuthProtocol, Cols) of
{value, {_, Protocol}} ->
Protocol;
false ->
@@ -1105,7 +1105,7 @@ get_auth_proto(RowIndex, Cols) ->
get_priv_proto(RowIndex, Cols) ->
%% The protocol can be changed by the request too, otherwise,
%% check the stored protocol.
- case lists:keysearch(?usmUserPrivProtocol, 1, Cols) of
+ case key1search(?usmUserPrivProtocol, Cols) of
{value, {_, Protocol}} ->
Protocol;
false ->
@@ -1243,6 +1243,27 @@ set_sname(_) -> %% Keep it, if already set.
error(Reason) ->
throw({error, Reason}).
+
+%%-----------------------------------------------------------------
+%% lists key-function(s) wrappers
+
+-compile({inline,key1delete/2}).
+key1delete(Key, List) ->
+ lists:keydelete(Key, 1, List).
+
+-compile({inline,key1search/2}).
+key1search(Key, List) ->
+ lists:keysearch(Key, 1, List).
+
+-compile({inline,key1store/3}).
+key1store(Key, List, Elem) ->
+ lists:keystore(Key, 1, List, Elem).
+
+-compile({inline,key1sort/1}).
+key1sort(List) ->
+ lists:keysort(1, List).
+
+
%%-----------------------------------------------------------------
info_msg(F, A) ->
--
cgit v1.2.3