From 6d5ac23e0b5aca3b27d9922e7f7448d6117b7aa4 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 20 Apr 2012 18:15:58 +0200 Subject: [snmp/manager] snmpm:log_to_io/6 did not use the LogName argument. Cut-and-paste error. OTP-10066 --- lib/snmp/src/manager/snmpm.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl index 89eaee9f80..f590892c66 100644 --- a/lib/snmp/src/manager/snmpm.erl +++ b/lib/snmp/src/manager/snmpm.erl @@ -1411,7 +1411,7 @@ log_to_io(LogDir, Mibs, LogName, LogFile) -> log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start). log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> - snmp:log_to_io(LogDir, Mibs, LogFile, Start, Stop). + snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop). change_log_size(NewSize) -> -- cgit v1.2.3 From 76e98a93821a0e628a465030bfcb63fd360afc8a Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 22 May 2012 11:45:03 +0200 Subject: [inets/httpc] Cosmetic update to pipeline test case Added (httpc) info printouts to all test case printouts. OYP-10092 --- lib/inets/test/httpc_SUITE.erl | 149 ++++++++++++++++++++++++----------------- 1 file changed, 88 insertions(+), 61 deletions(-) (limited to 'lib') diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index a116edef77..c4943cbb4c 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -761,47 +761,60 @@ http_inets_pipe(Config) when is_list(Config) -> test_pipeline(URL) -> - p("test_pipeline -> entry with" - "~n URL: ~p", [URL]), - - httpc:set_options([{pipeline_timeout, 50000}]), - - p("test_pipeline -> issue (async) request 1"), - {ok, RequestId1} = + p("test_pipeline -> entry with" + "~n URL: ~p", [URL]), + + httpc:set_options([{pipeline_timeout, 50000}]), + + p("test_pipeline -> issue (async) request 1" + "~n when profile info: ~p", [httpc:info()]), + {ok, RequestId1} = httpc:request(get, {URL, []}, [], [{sync, false}]), - test_server:format("RequestId1: ~p~n", [RequestId1]), - p("test_pipeline -> RequestId1: ~p", [RequestId1]), - - %% Make sure pipeline is initiated - p("test_pipeline -> sleep some", []), - test_server:sleep(4000), - - p("test_pipeline -> issue (async) request 2"), - {ok, RequestId2} = + tsp("RequestId1: ~p", [RequestId1]), + p("test_pipeline -> RequestId1: ~p" + "~n when profile info: ~p", [RequestId1, httpc:info()]), + + %% Make sure pipeline is initiated + p("test_pipeline -> sleep some", []), + test_server:sleep(4000), + + p("test_pipeline -> issue (async) request 2" + "~n when profile info: ~p", [httpc:info()]), + {ok, RequestId2} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId2: ~p", [RequestId2]), - p("test_pipeline -> RequestId2: ~p", [RequestId2]), - - p("test_pipeline -> issue (sync) request 3"), - {ok, {{_,200,_}, [_ | _], [_ | _]}} = + tsp("RequestId2: ~p", [RequestId2]), + p("test_pipeline -> RequestId2: ~p" + "~n when profile info: ~p", [RequestId2, httpc:info()]), + + p("test_pipeline -> issue (sync) request 3"), + {ok, {{_,200,_}, [_ | _], [_ | _]}} = httpc:request(get, {URL, []}, [], []), - - p("test_pipeline -> expect reply for (async) request 1 or 2"), + + p("test_pipeline -> expect reply for (async) request 1 or 2" + "~n when profile info: ~p", [httpc:info()]), receive {http, {RequestId1, {{_, 200, _}, _, _}}} -> - p("test_pipeline -> received reply for (async) request 1 - now wait for 2"), + p("test_pipeline -> " + "received reply for (async) request 1 - now wait for 2" + "~n when profile info: ~p", [httpc:info()]), receive {http, {RequestId2, {{_, 200, _}, _, _}}} -> - p("test_pipeline -> received reply for (async) request 2"), + p("test_pipeline -> " + "received reply for (async) request 2" + "~n when profile info: ~p", [httpc:info()]), ok; {http, Msg1} -> tsf(Msg1) end; {http, {RequestId2, {{_, 200, _}, _, _}}} -> - io:format("test_pipeline -> received reply for (async) request 2 - now wait for 1"), + io:format("test_pipeline -> " + "received reply for (async) request 2 - now wait for 1" + "~n when profile info: ~p", [httpc:info()]), receive {http, {RequestId1, {{_, 200, _}, _, _}}} -> - io:format("test_pipeline -> received reply for (async) request 1"), + io:format("test_pipeline -> " + "received reply for (async) request 1" + "~n when profile info: ~p", [httpc:info()]), ok; {http, Msg2} -> tsf(Msg2) @@ -814,38 +827,49 @@ test_pipeline(URL) -> tsf({error, {timeout, Any1}}) end end, - - p("test_pipeline -> sleep some"), - test_server:sleep(4000), - - p("test_pipeline -> issue (async) request 4"), - {ok, RequestId3} = + + p("test_pipeline -> sleep some" + "~n when profile info: ~p", [httpc:info()]), + test_server:sleep(4000), + + p("test_pipeline -> issue (async) request 4" + "~n when profile info: ~p", [httpc:info()]), + {ok, RequestId3} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId3: ~p", [RequestId3]), - p("test_pipeline -> RequestId3: ~p", [RequestId3]), - - p("test_pipeline -> issue (async) request 5"), - {ok, RequestId4} = + tsp("RequestId3: ~p", [RequestId3]), + p("test_pipeline -> RequestId3: ~p" + "~n when profile info: ~p", [RequestId3, httpc:info()]), + + p("test_pipeline -> issue (async) request 5" + "~n when profile info: ~p", [httpc:info()]), + {ok, RequestId4} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId4: ~p~n", [RequestId4]), - p("test_pipeline -> RequestId4: ~p", [RequestId4]), - - p("test_pipeline -> cancel (async) request 4"), - ok = httpc:cancel_request(RequestId3), - - p("test_pipeline -> expect *no* reply for cancelled (async) request 4 (for 3 secs)"), - receive - {http, {RequestId3, _}} -> - tsf(http_cancel_request_failed) - after 3000 -> - ok - end, - - p("test_pipeline -> expect reply for (async) request 4"), - Body = + tsp("RequestId4: ~p", [RequestId4]), + p("test_pipeline -> RequestId4: ~p" + "~n when profile info: ~p", [RequestId4, httpc:info()]), + + p("test_pipeline -> cancel (async) request 4" + "~n when profile info: ~p", [httpc:info()]), + ok = httpc:cancel_request(RequestId3), + + p("test_pipeline -> " + "expect *no* reply for cancelled (async) request 4 (for 3 secs)" + "~n when profile info: ~p", [httpc:info()]), + receive + {http, {RequestId3, _}} -> + tsf(http_cancel_request_failed) + after 3000 -> + ok + end, + + p("test_pipeline -> expect reply for (async) request 4" + "~n when profile info: ~p", [httpc:info()]), + Body = receive {http, {RequestId4, {{_, 200, _}, _, BinBody4}}} = Res -> - p("test_pipeline -> received reply for (async) request 5"), + p("test_pipeline -> " + "received reply for (async) request 5" + "~n when profile info: ~p", [httpc:info()]), tsp("Receive : ~p", [Res]), BinBody4; {http, Msg4} -> @@ -856,19 +880,22 @@ test_pipeline(URL) -> tsf({error, {timeout, Any2}}) end end, - - p("test_pipeline -> check reply for (async) request 5"), + + p("test_pipeline -> check reply for (async) request 5" + "~n when profile info: ~p", [httpc:info()]), inets_test_lib:check_body(binary_to_list(Body)), - - p("test_pipeline -> ensure no unexpected incomming"), + + p("test_pipeline -> ensure no unexpected incomming" + "~n when profile info: ~p", [httpc:info()]), receive {http, Any} -> tsf({unexpected_message, Any}) after 500 -> ok end, - - p("test_pipeline -> done"), + + p("test_pipeline -> done" + "~n when profile info: ~p", [httpc:info()]), ok. %%------------------------------------------------------------------------- -- cgit v1.2.3 From 2c27a2e2a57d37df1f33f481dc0edbfd2cc83db3 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 22 May 2012 14:53:45 +0200 Subject: [inets/httpc] Cancel request does not work Cancel request does not work due to incorrect handler table creation (wrong keypos). OTP-10092 --- lib/inets/src/http_client/httpc_manager.erl | 105 +++++++++-------- lib/inets/test/httpc_SUITE.erl | 177 +++++++++++++++------------- lib/inets/test/inets_test_lib.erl | 4 + 3 files changed, 154 insertions(+), 132 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index b225b43214..771968e169 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -59,17 +59,9 @@ options = #options{} }). --record(handler_info, - { - id, % Id of the request: request_id() - starter, % Pid of the handler starter process (temp): pid() - handler, % Pid of the handler process: pid() - from, % From for the request: from() - state % State of the handler: initiating | started | operational | canceled - }). - -define(DELAY, 500). + %%==================================================================== %% Internal Application API %%==================================================================== @@ -379,8 +371,7 @@ do_init(ProfileName, CookiesDir) -> %% Create handler db ?hcrt("create handler/request db", []), HandlerDbName = handler_db_name(ProfileName), - ets:new(HandlerDbName, - [protected, set, named_table, {keypos, #handler_info.id}]), + ets:new(HandlerDbName, [protected, set, named_table, {keypos, 1}]), %% Cookie DB ?hcrt("create cookie db", []), @@ -414,9 +405,10 @@ handle_call({request, Request}, _, State) -> {stop, Error, httpc_response:error(Request, Error), State} end; -handle_call({cancel_request, RequestId}, From, State) -> +handle_call({cancel_request, RequestId}, From, + #state{handler_db = HandlerDb} = State) -> ?hcri("cancel_request", [{request_id, RequestId}]), - case ets:lookup(State#state.handler_db, RequestId) of + case ets:lookup(HandlerDb, RequestId) of [] -> %% The request has allready compleated make sure %% it is deliverd to the client process queue so @@ -428,9 +420,9 @@ handle_call({cancel_request, RequestId}, From, State) -> {noreply, State}; [{_, Pid, _}] -> httpc_handler:cancel(RequestId, Pid, From), - {noreply, State#state{cancel = - [{RequestId, Pid, From} | - State#state.cancel]}} + {noreply, + State#state{cancel = + [{RequestId, Pid, From} | State#state.cancel]}} end; handle_call(reset_cookies, _, #state{cookie_db = CookieDb} = State) -> @@ -645,7 +637,7 @@ code_change(_, code_change(_, State, _) -> {ok, State}. -%% This function is to catch everything that calls through the cracks... +%% This function is used to catch everything that falls through the cracks... update_session_table(SessionDB, Transform) -> ets:safe_fixtable(SessionDB, true), update_session_table(SessionDB, ets:first(SessionDB), Transform), @@ -678,35 +670,42 @@ get_manager_info(#state{handler_db = HDB, CookieInfo = httpc_cookie:which_cookies(CDB), [{handlers, HandlerInfo}, {cookies, CookieInfo}]. +sort_handlers(Unsorted) -> + sort_handlers2(lists:keysort(1, Unsorted)). + +sort_handlers2([]) -> + []; +sort_handlers2([{HandlerPid, RequestId}|L]) -> + {Handler, Rest} = sort_handlers2(HandlerPid, [RequestId], L), + [Handler | sort_handlers2(Rest)]. + +sort_handlers2(HandlerPid, Reqs, []) -> + {{HandlerPid, lists:sort(Reqs)}, []}; +sort_handlers2(HandlerPid, Reqs, [{HandlerPid, ReqId}|Rest]) -> + sort_handlers2(HandlerPid, [ReqId|Reqs], Rest); +sort_handlers2(HandlerPid1, Reqs, [{HandlerPid2, _}|_] = Rest) + when HandlerPid1 =/= HandlerPid2 -> + {{HandlerPid1, lists:sort(Reqs)}, Rest}. + get_handler_info(Tab) -> - Pattern = #handler_info{handler = '$1', - state = '$2', - _ = '_'}, - Handlers1 = [{Pid, State} || [Pid, State] <- ets:match(Tab, Pattern)], - F = fun({Pid, State} = Elem, Acc) when State =/= canceled -> - case lists:keymember(Pid, 1, Acc) of - true -> - Acc; - false -> - [Elem | Acc] - end; - (_, Acc) -> - Acc - end, - Handlers2 = lists:foldl(F, [], Handlers1), - Handlers3 = [{Pid, State, - case (catch httpc_handler:info(Pid)) of - {'EXIT', _} -> + Pattern = {'$2', '$1', '_'}, + Handlers1 = [{Pid, Id} || [Pid, Id] <- ets:match(Tab, Pattern)], + Handlers2 = sort_handlers(Handlers1), + Handlers3 = [{Pid, Reqs, + try + begin + httpc_handler:info(Pid) + end + catch + _:_ -> %% Why would this crash? %% Only if the process has died, but we don't %% know about it? - []; - Else -> - Else - end} || - {Pid, State} <- Handlers2], + [] + end} || {Pid, Reqs} <- Handlers2], Handlers3. + handle_request(#request{settings = #http_options{version = "HTTP/0.9"}} = Request, State) -> @@ -758,19 +757,21 @@ handle_request(Request, State = #state{options = Options}) -> {reply, {ok, NewRequest#request.id}, State}. -start_handler(Request, State) -> +start_handler(#request{id = Id, + from = From} = Request, + #state{profile_name = ProfileName, + handler_db = HandlerDb, + options = Options}) -> {ok, Pid} = case is_inets_manager() of true -> httpc_handler_sup:start_child([whereis(httpc_handler_sup), - Request, State#state.options, - State#state.profile_name]); + Request, Options, ProfileName]); false -> - httpc_handler:start_link(self(), Request, State#state.options, - State#state.profile_name) + httpc_handler:start_link(self(), Request, Options, ProfileName) end, - ets:insert(State#state.handler_db, {Request#request.id, - Pid, Request#request.from}), + HandlerInfo = {Id, Pid, From}, + ets:insert(HandlerDb, HandlerInfo), erlang:monitor(process, Pid). @@ -827,12 +828,14 @@ select_session(Candidates, Max) -> {ok, HandlerPid} end. -pipeline_or_keep_alive(Request, HandlerPid, State) -> +pipeline_or_keep_alive(#request{id = Id, + from = From} = Request, + HandlerPid, + #state{handler_db = HandlerDb} = State) -> case (catch httpc_handler:send(Request, HandlerPid)) of ok -> - ets:insert(State#state.handler_db, {Request#request.id, - HandlerPid, - Request#request.from}); + HandlerInfo = {Id, HandlerPid, From}, + ets:insert(HandlerDb, HandlerInfo); _ -> % timeout pipelining failed start_handler(Request, State) end. diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index c4943cbb4c..1cdd96f0b0 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -768,120 +768,83 @@ test_pipeline(URL) -> p("test_pipeline -> issue (async) request 1" "~n when profile info: ~p", [httpc:info()]), - {ok, RequestId1} = + {ok, RequestIdA1} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId1: ~p", [RequestId1]), - p("test_pipeline -> RequestId1: ~p" - "~n when profile info: ~p", [RequestId1, httpc:info()]), + tsp("RequestIdA1: ~p", [RequestIdA1]), + p("test_pipeline -> RequestIdA1: ~p" + "~n when profile info: ~p", [RequestIdA1, httpc:info()]), %% Make sure pipeline is initiated p("test_pipeline -> sleep some", []), test_server:sleep(4000), - p("test_pipeline -> issue (async) request 2" + p("test_pipeline -> issue (async) request A2, A3 and A4" "~n when profile info: ~p", [httpc:info()]), - {ok, RequestId2} = + {ok, RequestIdA2} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId2: ~p", [RequestId2]), - p("test_pipeline -> RequestId2: ~p" - "~n when profile info: ~p", [RequestId2, httpc:info()]), + {ok, RequestIdA3} = + httpc:request(get, {URL, []}, [], [{sync, false}]), + {ok, RequestIdA4} = + httpc:request(get, {URL, []}, [], [{sync, false}]), + tsp("RequestIdAs => A2: ~p, A3: ~p and A4: ~p", + [RequestIdA2, RequestIdA3, RequestIdA4]), + p("test_pipeline -> RequestIds => A2: ~p, A3: ~p and A4: ~p" + "~n when profile info: ~p", + [RequestIdA2, RequestIdA3, RequestIdA4, httpc:info()]), p("test_pipeline -> issue (sync) request 3"), {ok, {{_,200,_}, [_ | _], [_ | _]}} = httpc:request(get, {URL, []}, [], []), - p("test_pipeline -> expect reply for (async) request 1 or 2" + p("test_pipeline -> expect reply for (async) request A1, A2, A3 and A4" "~n when profile info: ~p", [httpc:info()]), - receive - {http, {RequestId1, {{_, 200, _}, _, _}}} -> - p("test_pipeline -> " - "received reply for (async) request 1 - now wait for 2" - "~n when profile info: ~p", [httpc:info()]), - receive - {http, {RequestId2, {{_, 200, _}, _, _}}} -> - p("test_pipeline -> " - "received reply for (async) request 2" - "~n when profile info: ~p", [httpc:info()]), - ok; - {http, Msg1} -> - tsf(Msg1) - end; - {http, {RequestId2, {{_, 200, _}, _, _}}} -> - io:format("test_pipeline -> " - "received reply for (async) request 2 - now wait for 1" - "~n when profile info: ~p", [httpc:info()]), - receive - {http, {RequestId1, {{_, 200, _}, _, _}}} -> - io:format("test_pipeline -> " - "received reply for (async) request 1" - "~n when profile info: ~p", [httpc:info()]), - ok; - {http, Msg2} -> - tsf(Msg2) - end; - {http, Msg3} -> - tsf(Msg3) - after 60000 -> - receive Any1 -> - tsp("received crap after timeout: ~n ~p", [Any1]), - tsf({error, {timeout, Any1}}) - end - end, - + pipeline_await_async_reply([{RequestIdA1, a1, 200}, + {RequestIdA2, a2, 200}, + {RequestIdA3, a3, 200}, + {RequestIdA4, a4, 200}], ?MINS(1)), + p("test_pipeline -> sleep some" "~n when profile info: ~p", [httpc:info()]), test_server:sleep(4000), - p("test_pipeline -> issue (async) request 4" + p("test_pipeline -> issue (async) request B1, B2, B3 and B4" "~n when profile info: ~p", [httpc:info()]), - {ok, RequestId3} = + {ok, RequestIdB1} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId3: ~p", [RequestId3]), - p("test_pipeline -> RequestId3: ~p" - "~n when profile info: ~p", [RequestId3, httpc:info()]), - - p("test_pipeline -> issue (async) request 5" - "~n when profile info: ~p", [httpc:info()]), - {ok, RequestId4} = + {ok, RequestIdB2} = + httpc:request(get, {URL, []}, [], [{sync, false}]), + {ok, RequestIdB3} = httpc:request(get, {URL, []}, [], [{sync, false}]), - tsp("RequestId4: ~p", [RequestId4]), - p("test_pipeline -> RequestId4: ~p" - "~n when profile info: ~p", [RequestId4, httpc:info()]), + {ok, RequestIdB4} = + httpc:request(get, {URL, []}, [], [{sync, false}]), + tsp("RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p", + [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4]), + p("test_pipeline -> RequestIdBs => B1: ~p, B2: ~p, B3: ~p and B4: ~p" + "~n when profile info: ~p", + [RequestIdB1, RequestIdB2, RequestIdB3, RequestIdB4, httpc:info()]), - p("test_pipeline -> cancel (async) request 4" + p("test_pipeline -> cancel (async) request B2" "~n when profile info: ~p", [httpc:info()]), - ok = httpc:cancel_request(RequestId3), + ok = httpc:cancel_request(RequestIdB2), p("test_pipeline -> " - "expect *no* reply for cancelled (async) request 4 (for 3 secs)" + "expect *no* reply for cancelled (async) request B2 (for 3 secs)" "~n when profile info: ~p", [httpc:info()]), receive - {http, {RequestId3, _}} -> + {http, {RequestIdB2, _}} -> tsf(http_cancel_request_failed) after 3000 -> ok end, - p("test_pipeline -> expect reply for (async) request 4" + p("test_pipeline -> expect reply for (async) request B1, B3 and B4" "~n when profile info: ~p", [httpc:info()]), - Body = - receive - {http, {RequestId4, {{_, 200, _}, _, BinBody4}}} = Res -> - p("test_pipeline -> " - "received reply for (async) request 5" - "~n when profile info: ~p", [httpc:info()]), - tsp("Receive : ~p", [Res]), - BinBody4; - {http, Msg4} -> - tsf(Msg4) - after 60000 -> - receive Any2 -> - tsp("received crap after timeout: ~n ~p", [Any2]), - tsf({error, {timeout, Any2}}) - end - end, - - p("test_pipeline -> check reply for (async) request 5" + Bodies = pipeline_await_async_reply([{RequestIdB1, b1, 200}, + {RequestIdB3, b3, 200}, + {RequestIdB4, b4, 200}], ?MINS(1)), + [{b1, Body}|_] = Bodies, + + p("test_pipeline -> check reply for (async) request B1" "~n when profile info: ~p", [httpc:info()]), inets_test_lib:check_body(binary_to_list(Body)), @@ -898,6 +861,58 @@ test_pipeline(URL) -> "~n when profile info: ~p", [httpc:info()]), ok. +pipeline_await_async_reply(ReqIds, Timeout) -> + pipeline_await_async_reply(ReqIds, Timeout, []). + +pipeline_await_async_reply([], _, Acc) -> + lists:keysort(1, Acc); +pipeline_await_async_reply(ReqIds, Timeout, Acc) when Timeout > 0 -> + T1 = inets_test_lib:timestamp(), + p("pipeline_await_async_reply -> await replies" + "~n ReqIds: ~p" + "~n Timeout: ~p", [ReqIds, Timeout]), + receive + {http, {RequestId, {{_, Status, _}, _, Body}}} -> + p("pipeline_await_async_reply -> received reply for" + "~n RequestId: ~p" + "~n Status: ~p", [RequestId, Status]), + case lists:keysearch(RequestId, 1, ReqIds) of + {value, {RequestId, N, Status}} -> + p("pipeline_await_async_reply -> " + "found expected request ~w", [N]), + ReqIds2 = lists:keydelete(RequestId, 1, ReqIds), + NewTimeout = Timeout - (inets_test_lib:timestamp()-T1), + pipeline_await_async_reply(ReqIds2, NewTimeout, + [{N, Body} | Acc]); + {value, {RequestId, N, WrongStatus}} -> + p("pipeline_await_async_reply -> " + "found request ~w with wrong status", [N]), + tsf({reply_with_unexpected_status, + {RequestId, N, WrongStatus}}); + false -> + tsf({unexpected_reply, {RequestId, Status}}) + end; + {http, Msg} -> + tsf({unexpected_reply, Msg}) + after Timeout -> + receive + Any -> + tsp("pipeline_await_async_reply -> " + "received unknown data after timeout: " + "~n ~p", [Any]), + tsf({timeout, {unknown, Any}}) + end + end; +pipeline_await_async_reply(ReqIds, _, Acc) -> + tsp("pipeline_await_async_reply -> " + "timeout: " + "~n ~p" + "~nwhen" + "~n ~p", [ReqIds, Acc]), + tsf({timeout, ReqIds, Acc}). + + + %%------------------------------------------------------------------------- http_trace(doc) -> ["Perform a TRACE request that goes through a proxy."]; diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl index c94be796cd..7f4b0ec8d8 100644 --- a/lib/inets/test/inets_test_lib.erl +++ b/lib/inets/test/inets_test_lib.erl @@ -31,6 +31,7 @@ send/3, close/2]). -export([copy_file/3, copy_files/2, copy_dirs/2, del_dirs/1]). -export([info/4, log/4, debug/4, print/4]). +-export([timestamp/0, formated_timestamp/0]). -export([tsp/1, tsp/2, tsf/1, tss/1]). -export([check_body/1]). -export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]). @@ -642,6 +643,9 @@ tsf(Reason) -> tss(Time) -> test_server:sleep(Time). +timestamp() -> + http_util:timestamp(). + formated_timestamp() -> format_timestamp( os:timestamp() ). -- cgit v1.2.3 From b1d12bf8623c5585017b1777236c18da1f5a83a4 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 22 May 2012 15:01:06 +0200 Subject: [inets/httpc] Updated version, release nodes and appup OTP-10092 --- lib/inets/doc/src/notes.xml | 91 +++++++++++++++++++++++++++++++++ lib/inets/src/inets_app/inets.appup.src | 10 ++++ lib/inets/vsn.mk | 2 +- 3 files changed, 102 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index dfdeb4016c..9e1da12f4a 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -33,6 +33,97 @@ +
Inets 5.9.1 + +
Improvements and New Features +

-

+ + + +
+ +
Fixed Bugs and Malfunctions + + + + +

[httpc] Cancel request does not work due to incorrect + handler table creation (wrong keypos).

+

Vyacheslav Vorobyov

+

Own Id: OTP-10092

+
+ +
+ +
+ +
+ Incompatibilities +

-

+ + + +
+ +
+ +
Inets 5.9
Improvements and New Features diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index c7029f7b31..0a69636851 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -18,6 +18,11 @@ {"%VSN%", [ + {"5.9", + [ + {update, httpc_handler, soft, soft_purge, soft_purge, []} + ] + }, {"5.8.1", [ {load_module, http_uri, soft_purge, soft_purge, []}, @@ -74,6 +79,11 @@ } ], [ + {"5.9", + [ + {update, httpc_handler, soft, soft_purge, soft_purge, []} + ] + }, {"5.8.1", [ {load_module, http_uri, soft_purge, soft_purge, []}, diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 488947c3a1..949eceea7f 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 5.9 +INETS_VSN = 5.9.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" -- cgit v1.2.3 From ef14221acafe78b7a77b5d42b6a615fa7333750d Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 22 May 2012 15:35:26 +0200 Subject: [inets/httpc] Corrected appup file OTP-10092 --- lib/inets/src/inets_app/inets.appup.src | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index 0a69636851..93fd5b9595 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -20,7 +20,7 @@ [ {"5.9", [ - {update, httpc_handler, soft, soft_purge, soft_purge, []} + {update, httpc_manager, soft, soft_purge, soft_purge, []} ] }, {"5.8.1", @@ -40,6 +40,7 @@ {load_module, httpd_script_env, soft_purge, soft_purge, []}, {load_module, inets, soft_purge, soft_purge, [inets_trace]}, + {update, httpc_manager, soft, soft_purge, soft_purge, []}, {update, httpc_handler, soft, soft_purge, soft_purge, []}, {update, httpd_sup, soft, soft_purge, soft_purge, []}, {add_module, inets_trace} @@ -81,7 +82,7 @@ [ {"5.9", [ - {update, httpc_handler, soft, soft_purge, soft_purge, []} + {update, httpc_manager, soft, soft_purge, soft_purge, []} ] }, {"5.8.1", @@ -101,6 +102,7 @@ {load_module, httpd_script_env, soft_purge, soft_purge, []}, {load_module, inets, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, []}, {update, httpc_handler, soft, soft_purge, soft_purge, []}, {update, httpd_sup, soft, soft_purge, soft_purge, []}, {remove, {inets_trace, soft_purge, brutal_purge}} -- cgit v1.2.3 From 022bc68b6dd10624b58779dc2b3b0e392e3e04f5 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 22 May 2012 17:37:33 +0200 Subject: [inets/httpc] Better handling of session db update failure A failure to update the session database will now result in an informative error message and a controlled (handler) exit rather then an ugly crash. Also debug functions to retrieve sessions info and updated the info function with more info (sessions and options). OTP-10093 --- lib/inets/src/http_client/httpc.erl | 26 +++++++- lib/inets/src/http_client/httpc_handler.erl | 27 ++++++++- lib/inets/src/http_client/httpc_manager.erl | 92 ++++++++++++++++++++++++++--- 3 files changed, 135 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index f4802fb96d..b6e7708353 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -39,6 +39,7 @@ cookie_header/1, cookie_header/2, cookie_header/3, which_cookies/0, which_cookies/1, reset_cookies/0, reset_cookies/1, + which_sessions/0, which_sessions/1, stream_next/1, default_profile/0, profile_name/1, profile_name/2, @@ -267,6 +268,7 @@ set_option(Key, Value, Profile) -> %% Reason - term() %% Description: Retrieves the current options. %%------------------------------------------------------------------------- + get_options() -> record_info(fields, options). @@ -373,8 +375,6 @@ cookie_header(Url, Opts, Profile) {error, {not_started, Profile}} end. - - %%-------------------------------------------------------------------------- %% which_cookies() -> [cookie()] @@ -397,6 +397,28 @@ which_cookies(Profile) -> end. +%%-------------------------------------------------------------------------- +%% which_sessions() -> {GoodSession, BadSessions, NonSessions} +%% which_sessions(Profile) -> {GoodSession, BadSessions, NonSessions} +%% +%% Description: Debug function, dumping the sessions database, sorted +%% into three groups (Good-, Bad- and Non-sessions). +%%------------------------------------------------------------------------- +which_sessions() -> + which_sessions(default_profile()). + +which_sessions(Profile) -> + ?hcrt("which sessions", [{profile, Profile}]), + try + begin + httpc_manager:which_sessions(profile_name(Profile)) + end + catch + exit:{noproc, _} -> + {[], [], []} + end. + + %%-------------------------------------------------------------------------- %% info() -> list() %% info(Profile) -> list() diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl index b8c34bd99b..6fe05dec80 100644 --- a/lib/inets/src/http_client/httpc_handler.erl +++ b/lib/inets/src/http_client/httpc_handler.erl @@ -1713,7 +1713,32 @@ update_session(ProfileName, #session{id = SessionId} = Session, Pos, Value) -> catch error:undef -> % This could happen during code upgrade Session2 = erlang:setelement(Pos, Session, Value), - insert_session(Session2, ProfileName) + insert_session(Session2, ProfileName); + T:E -> + error_logger:error_msg("Failed updating session: " + "~n ProfileName: ~p" + "~n SessionId: ~p" + "~n Pos: ~p" + "~n Value: ~p" + "~nwhen" + "~n Session (db) info: ~p" + "~n Session (db): ~p" + "~n Session (record): ~p" + "~n T: ~p" + "~n E: ~p", + [ProfileName, SessionId, Pos, Value, + (catch httpc_manager:which_session_info(ProfileName)), + Session, + (catch httpc_manager:lookup_session(ProfileName, SessionId)), + T, E]), + exit({failed_updating_session, + [{profile, ProfileName}, + {session_id, SessionId}, + {pos, Pos}, + {value, Value}, + {etype, T}, + {error, E}, + {stacktrace, erlang:get_stacktrace()}]}) end. diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index 771968e169..3612b331e7 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -34,8 +34,11 @@ retry_request/2, redirect_request/2, insert_session/2, + lookup_session/2, update_session/4, delete_session/2, + which_sessions/1, + which_session_info/1, set_options/2, get_options/2, store_cookies/3, @@ -186,6 +189,21 @@ insert_session(Session, ProfileName) -> ets:insert(SessionDbName, Session). +%%-------------------------------------------------------------------- +%% Function: lookup_session(SessionId, ProfileName) -> _ +%% SessionId - term() +%% ProfileName - atom() +%% +%% Description: Looks up a session record in the httpc manager +%% table __session_db. +%%-------------------------------------------------------------------- + +lookup_session(SessionId, ProfileName) -> + SessionDbName = session_db_name(ProfileName), + ?hcrt("lookup session", [{session_id, SessionId}, {profile, ProfileName}]), + ets:lookup(SessionDbName, SessionId). + + %%-------------------------------------------------------------------- %% Function: update_session(ProfileName, SessionId, Pos, Value) -> _ %% Session - #session{} @@ -193,7 +211,7 @@ insert_session(Session, ProfileName) -> %% %% Description: Update, only one field (Pos) of the session record %% identified by the SessionId, the session information -%% of the httpc manager table _session_db. +%% of the httpc manager table __session_db. %% Intended to be called by the httpc request handler process. %%-------------------------------------------------------------------- @@ -208,12 +226,12 @@ update_session(ProfileName, SessionId, Pos, Value) -> %%-------------------------------------------------------------------- -%% Function: delete_session(SessionId, ProfileName) -> _ +%% Function: delete_session(SessionId, ProfileName) -> void() %% SessionId - {{Host, Port}, HandlerPid} %% ProfileName - atom() %% %% Description: Deletes session information from the httpc manager -%% table httpc_manager_session_db_. Intended to be called by +%% table __session_db. Intended to be called by %% the httpc request handler process. %%-------------------------------------------------------------------- @@ -223,6 +241,57 @@ delete_session(SessionId, ProfileName) -> ets:delete(SessionDbName, SessionId). +%%-------------------------------------------------------------------- +%% Function: which sessions(ProfileName) -> SessionsInfo +%% ProfileName - atom() +%% SessionsInfo - {GoodSessions, BadSessions, NonSessions} +%% GoodSessions - [#session{}] +%% BadSessions - [tuple()] +%% NonSessions - [term()] +%% +%% Description: Produces a list of all sessions in the session db. +%% Used for debugging and since that is the intent, there is some +%% checking and transforming done, which produces the results. +%%-------------------------------------------------------------------- + +which_sessions(ProfileName) -> + ?hcrt("which_sessions", [{profile, ProfileName}]), + SessionDbName = session_db_name(ProfileName), + which_sessions2(SessionDbName). + +which_sessions2(SessionDbName) -> + Sessions = which_sessions_order(ets:tab2list(SessionDbName)), + GoodSessions = [GoodSession || {good_session, GoodSession} <- Sessions], + BadSessions = [BadSession || {bad_session, BadSession} <- Sessions], + NonSessions = [NonSession || {non_session, NonSession} <- Sessions], + {lists:keysort(#session.id, GoodSessions), + lists:keysort(#session.id, BadSessions), + lists:sort(NonSessions)}. + +which_sessions_order([]) -> + []; +which_sessions_order([Session|Sessions]) when is_record(Session, session) -> + [{good_session, Session} | which_sessions_order(Sessions)]; +which_sessions_order([BadSession|Sessions]) + when is_tuple(BadSession) andalso + (element(1, BadSession) =:= session) -> + [{bad_session, BadSession} | which_sessions_order(Sessions)]; +which_sessions_order([NonSession|Sessions]) -> + [{non_session, NonSession} | which_sessions_order(Sessions)]. + + +%%-------------------------------------------------------------------- +%% Function: which session_info(ProfileName) -> list() +%% +%% Description: Produces a ets table info list of the sessions table +%%-------------------------------------------------------------------- + +which_session_info(ProfileName) -> + SessionDbName = session_db_name(ProfileName), + ?hcrt("which_session_info", [{profile, ProfileName}]), + ets:info(SessionDbName). + + %%-------------------------------------------------------------------- %% Function: set_options(Options, ProfileName) -> ok %% @@ -449,8 +518,8 @@ handle_call({which_cookies, Url, Options}, _, handle_call({get_options, OptionItems}, _, #state{options = Options} = State) -> ?hcrv("get options", [{option_items, OptionItems}]), - Reply = [{OptionItem, get_option(OptionItem, Options)} || OptionItem <- - OptionItems], + Reply = [{OptionItem, get_option(OptionItem, Options)} || + OptionItem <- OptionItems], {reply, Reply, State}; handle_call(info, _, State) -> @@ -665,10 +734,19 @@ update_session_table(SessionDB, Key, Transform) -> %%-------------------------------------------------------------------- get_manager_info(#state{handler_db = HDB, - cookie_db = CDB} = _State) -> + session_db = SDB, + cookie_db = CDB, + options = Options} = _State) -> HandlerInfo = get_handler_info(HDB), + SessionInfo = which_sessions2(SDB), + OptionsInfo = + [{Item, get_option(Item, Options)} || + Item <- record_info(fields, options)], CookieInfo = httpc_cookie:which_cookies(CDB), - [{handlers, HandlerInfo}, {cookies, CookieInfo}]. + [{handlers, HandlerInfo}, + {sessions, SessionInfo}, + {options, OptionsInfo}, + {cookies, CookieInfo}]. sort_handlers(Unsorted) -> sort_handlers2(lists:keysort(1, Unsorted)). -- cgit v1.2.3 From 76ffc030fc320d436b0a540a20783d5d317ae761 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 22 May 2012 18:05:07 +0200 Subject: [inets/httpc] Updated docs, release notes and appup Added documentation for new (httpc:which_sessions/0,1) and updated (httpc:info/0,1) functions. Also updated appup. OTP-10093 --- lib/inets/doc/src/httpc.xml | 38 ++++++++++++ lib/inets/doc/src/notes.xml | 101 ++++++++++---------------------- lib/inets/src/inets_app/inets.appup.src | 68 ++++----------------- 3 files changed, 83 insertions(+), 124 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index 70c845bade..0e6abf3c65 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -648,6 +648,8 @@ apply(Module, Function, [ReplyInfo | Args])

Resets (clears) the cookie database for the specified Profile. If no profile is specified the default profile will be used.

+ + @@ -667,6 +669,42 @@ apply(Module, Function, [ReplyInfo | Args])

This function produces a list of the entire cookie database. It is intended for debugging/testing purposes. If no profile is specified the default profile will be used.

+ + + + + + + which_sessions() -> session_info() + which_sessions(Profile) -> session_info() + Produces a slightly processed dump of the sessions database. + + Profile = profile() | pid() (when started stand_alone) + session_info() = {GoodSessions, BadSessions, NonSessions} + GoodSessions = session() + BadSessions = tuple() + NonSessions = term() + + +

This function produces a slightly processed dump of the session + database. It is intended for debugging. + If no profile is specified the default profile will be used.

+ + +
+
+ + + info() -> list() + info(Profile) -> list() + Produces a list of miscelleneous info + + Profile = profile() | pid() (when started stand_alone) + + +

This function produces a list of miscelleneous info. + It is intended for debugging. + If no profile is specified the default profile will be used.

diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 9e1da12f4a..8ed07f5c94 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -36,53 +36,23 @@
Inets 5.9.1
Improvements and New Features + -
@@ -103,11 +73,11 @@
+
+-->
@@ -193,11 +163,11 @@ + +--> @@ -376,31 +346,6 @@ -
- Incompatibilities - - - - -

[httpc] Deprecated interface module http has been removed. - It has (long) been replaced by http client interface module - httpc.

-

Own Id: OTP-9359

-
- - -

[httpc|httpd] The old ssl implementation (based on OpenSSL), - has been deprecated. The config option that specified usage of - this version of the ssl app, ossl, has been removed.

-

Own Id: OTP-9522

-
- -
- -
-
Fixed Bugs and Malfunctions +
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index 93fd5b9595..a3a3205f65 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -20,7 +20,9 @@ [ {"5.9", [ - {update, httpc_manager, soft, soft_purge, soft_purge, []} + {load_module, httpc, soft_purge, soft_purge, [httpc_manager]}, + {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, + {update, httpc_manager, soft, soft_purge, soft_purge, []} ] }, {"5.8.1", @@ -30,7 +32,6 @@ {load_module, httpc, soft_purge, soft_purge, [http_uri, httpc_manager]}, - {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]}, {load_module, inets_app, soft_purge, soft_purge, [inets_sup]}, {update, inets_sup, soft, soft_purge, soft_purge, []}, @@ -40,37 +41,15 @@ {load_module, httpd_script_env, soft_purge, soft_purge, []}, {load_module, inets, soft_purge, soft_purge, [inets_trace]}, - {update, httpc_manager, soft, soft_purge, soft_purge, []}, - {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]}, + {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, {update, httpd_sup, soft, soft_purge, soft_purge, []}, {add_module, inets_trace} ] }, - {"5.8", + {"5.8", [ - {load_module, http_uri, soft_purge, soft_purge, []}, - {load_module, httpc_response, soft_purge, soft_purge, [http_uri]}, - - {load_module, httpc, soft_purge, soft_purge, - [http_uri, httpc_manager]}, - - {load_module, inets_app, soft_purge, soft_purge, [inets_sup]}, - {update, inets_sup, soft, soft_purge, soft_purge, []}, - - {load_module, inets, soft_purge, soft_purge, [inets_trace]}, - - {load_module, httpd_conf, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, []}, - {load_module, httpd_script_env, soft_purge, soft_purge, []}, - - {load_module, ftp, soft_purge, soft_purge, []}, - {update, httpc_handler, {advanced, upgrade_from_pre_5_8_1}, - soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, upgrade_from_pre_5_8_1}, - soft_purge, soft_purge, [http_uri, httpc_handler]}, - {update, httpd_sup, soft, soft_purge, soft_purge, []}, - - {add_module, inets_trace} + {restart_application, inets} ] }, {"5.7.2", @@ -82,7 +61,9 @@ [ {"5.9", [ - {update, httpc_manager, soft, soft_purge, soft_purge, []} + {load_module, httpc, soft_purge, soft_purge, [httpc_manager]}, + {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, + {update, httpc_manager, soft, soft_purge, soft_purge, []} ] }, {"5.8.1", @@ -92,7 +73,6 @@ {load_module, httpc, soft_purge, soft_purge, [http_uri, httpc_manager]}, - {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]}, {load_module, inets_app, soft_purge, soft_purge, [inets_sup]}, {update, inets_sup, soft, soft_purge, soft_purge, []}, @@ -102,37 +82,15 @@ {load_module, httpd_script_env, soft_purge, soft_purge, []}, {load_module, inets, soft_purge, soft_purge, []}, - {update, httpc_manager, soft, soft_purge, soft_purge, []}, - {update, httpc_handler, soft, soft_purge, soft_purge, []}, + {update, httpc_manager, soft, soft_purge, soft_purge, [http_uri]}, + {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, {update, httpd_sup, soft, soft_purge, soft_purge, []}, {remove, {inets_trace, soft_purge, brutal_purge}} ] }, {"5.8", [ - {load_module, http_uri, soft_purge, soft_purge, []}, - {load_module, httpc_response, soft_purge, soft_purge, [http_uri]}, - - {load_module, httpc, soft_purge, soft_purge, - [http_uri, httpc_manager]}, - - {load_module, inets_app, soft_purge, soft_purge, [inets_sup]}, - {update, inets_sup, soft, soft_purge, soft_purge, []}, - - {load_module, inets, soft_purge, soft_purge, []}, - - {load_module, httpd_conf, soft_purge, soft_purge, []}, - {load_module, httpd_response, soft_purge, soft_purge, []}, - {load_module, httpd_script_env, soft_purge, soft_purge, []}, - - {load_module, ftp, soft_purge, soft_purge, []}, - {update, httpc_handler, {advanced, upgrade_from_pre_5_8_1}, - soft_purge, soft_purge, []}, - {update, httpc_manager, {advanced, upgrade_from_pre_5_8_1}, - soft_purge, soft_purge, [http_uri, httpc_handler]}, - {update, httpd_sup, soft, soft_purge, soft_purge, []}, - - {remove, {inets_trace, soft_purge, brutal_purge}} + {restart_application, inets} ] }, {"5.7.2", -- cgit v1.2.3 From 4c5c287cfe234b8daaf8ead712edc43aa419949b Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 23 May 2012 14:54:56 +0200 Subject: [inets] Removed R14B compatible version of behaviour definition Removed R14B compatible version of (inets-service and tftp) behaviour definition. OTP-10095 --- lib/inets/doc/src/notes.xml | 10 ++++++++-- lib/inets/src/inets_app/inets.appup.src | 10 ++++++++++ lib/inets/src/inets_app/inets.mk | 6 +----- lib/inets/src/inets_app/inets_service.erl | 17 +---------------- lib/inets/src/tftp/tftp.erl | 18 +----------------- 5 files changed, 21 insertions(+), 40 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 8ed07f5c94..9a2fced12e 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -42,16 +42,22 @@ -

Better handling of errorI(s) during update of the session +

Better handling of error(s) during update of the session database.

Also added and updated some debugging functions - which_sessions/10,1 + which_sessions/0,1 and info/0.

Own Id: OTP-10093

Aux Id: Seq 12062

+ +

Removed R14B compatible version of (inets-service and + tftp) behaviour definition.

+

Own Id: OTP-10095

+
+
diff --git a/lib/inets/src/inets_app/inets.appup.src b/lib/inets/src/inets_app/inets.appup.src index a3a3205f65..2adb2a0fc8 100644 --- a/lib/inets/src/inets_app/inets.appup.src +++ b/lib/inets/src/inets_app/inets.appup.src @@ -20,6 +20,8 @@ [ {"5.9", [ + {load_module, tftp, soft_purge, soft_purge, [inets_service]}, + {load_module, inets_service, soft_purge, soft_purge, []}, {load_module, httpc, soft_purge, soft_purge, [httpc_manager]}, {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, {update, httpc_manager, soft, soft_purge, soft_purge, []} @@ -27,6 +29,9 @@ }, {"5.8.1", [ + {load_module, tftp, soft_purge, soft_purge, [inets_service]}, + {load_module, inets_service, soft_purge, soft_purge, []}, + {load_module, http_uri, soft_purge, soft_purge, []}, {load_module, httpc_response, soft_purge, soft_purge, [http_uri]}, @@ -61,6 +66,8 @@ [ {"5.9", [ + {load_module, tftp, soft_purge, soft_purge, [inets_service]}, + {load_module, inets_service, soft_purge, soft_purge, []}, {load_module, httpc, soft_purge, soft_purge, [httpc_manager]}, {update, httpc_handler, soft, soft_purge, soft_purge, [httpc_manager]}, {update, httpc_manager, soft, soft_purge, soft_purge, []} @@ -68,6 +75,9 @@ }, {"5.8.1", [ + {load_module, tftp, soft_purge, soft_purge, [inets_service]}, + {load_module, inets_service, soft_purge, soft_purge, []}, + {load_module, http_uri, soft_purge, soft_purge, []}, {load_module, httpc_response, soft_purge, soft_purge, [http_uri]}, diff --git a/lib/inets/src/inets_app/inets.mk b/lib/inets/src/inets_app/inets.mk index d24cc0aea3..adef32dc19 100644 --- a/lib/inets/src/inets_app/inets.mk +++ b/lib/inets/src/inets_app/inets.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2010-2011. All Rights Reserved. +# Copyright Ericsson AB 2010-2012. 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 @@ -33,10 +33,6 @@ ifeq ($(WARN_UNUSED_WARS), true) ERL_COMPILE_FLAGS += +warn_unused_vars endif -ifeq ($(shell erl -noshell -eval 'io:format("~4s", [erlang:system_info(otp_release)])' -s init stop), R14B) -INETS_ERL_COMPILE_FLAGS += -D'OTP-R14B-COMPILER' -endif - INETS_APP_VSN_COMPILE_FLAGS = \ +'{parse_transform,sys_pre_attributes}' \ +'{attribute,insert,app_vsn,$(APP_VSN)}' diff --git a/lib/inets/src/inets_app/inets_service.erl b/lib/inets/src/inets_app/inets_service.erl index a057a51e2c..d17fdfe13e 100644 --- a/lib/inets/src/inets_app/inets_service.erl +++ b/lib/inets/src/inets_app/inets_service.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2011. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. 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 @@ -20,20 +20,6 @@ -module(inets_service). --ifdef('OTP-R14B-COMPILER'). - --export([behaviour_info/1]). - -behaviour_info(callbacks) -> - [{start_standalone, 1}, - {start_service, 1}, - {stop_service, 1}, - {services, 0}, - {service_info, 1}]; -behaviour_info(_) -> - undefined. - --else. %% Starts service stand-alone %% start_standalone(Config) -> % {ok, Pid} | {error, Reason} @@ -83,4 +69,3 @@ behaviour_info(_) -> -callback service_info(Service :: term()) -> {ok, [{Property :: term(), Value :: term()}]} | {error, Reason :: term()}. --endif. diff --git a/lib/inets/src/tftp/tftp.erl b/lib/inets/src/tftp/tftp.erl index 0d7ae1a89e..1621add246 100644 --- a/lib/inets/src/tftp/tftp.erl +++ b/lib/inets/src/tftp/tftp.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2011. All Rights Reserved. +%% Copyright Ericsson AB 2005-2012. 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 @@ -224,20 +224,6 @@ service_info/1 ]). --ifdef('OTP-R14B-COMPILER'). - --export([behaviour_info/1]). - -behaviour_info(callbacks) -> - [{prepare, 6}, - {open, 6}, - {read, 1}, - {write, 2}, - {abort, 3}]; -behaviour_info(_) -> - undefined. - --else. -type peer() :: {PeerType :: inet | inet6, PeerHost :: inet:ip_address(), @@ -280,8 +266,6 @@ behaviour_info(_) -> -callback abort(Code :: error_code(), string(), State :: term()) -> 'ok'. --endif. - -include("tftp.hrl"). -- cgit v1.2.3 From 517315f2a0f5f9f51ba6b58959f93a38ad24047c Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 23 May 2012 18:46:56 +0200 Subject: [inets] Fixed release notes OTP-10095 --- lib/inets/doc/src/notes.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index 9a2fced12e..b6e8be467f 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -44,10 +44,11 @@

Better handling of error(s) during update of the session database.

-

Also added and updated some debugging functions - which_sessions/0,1 - and - info/0.

+

Also added + (which_sessions/0,1) + and updated and documented + (info/0) + some debugging functions.

Own Id: OTP-10093

Aux Id: Seq 12062

-- cgit v1.2.3 From 1bc041bd68040220081e8af275701f92f4a07aae Mon Sep 17 00:00:00 2001 From: Jesper Louis Andersen Date: Fri, 8 Jun 2012 19:18:06 +0200 Subject: Elaborate on timeouts in the httpc documentation All timeouts are in milliseconds. Reflect this in the documentation so it is explicit that it is so. --- lib/inets/doc/src/httpc.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index 70c845bade..f032ac96e1 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -488,7 +488,7 @@ apply(Module, Function, [ReplyInfo | Args]) KeepAliveTimeout = integer() Default is 120000 (= 2 min). If a persistent connection is idle longer than the - keep_alive_timeout the client will close the connection. + keep_alive_timeout in milliseconds, the client will close the connection. The server may also have such a time out but you should not count on it! MaxPipeline = integer() @@ -498,7 +498,7 @@ apply(Module, Function, [ReplyInfo | Args]) Default is 0, which will result in pipelining not being used. If a persistent connection is idle longer than the - pipeline_timeout the client will close the connection. + pipeline_timeout in milliseconds the client will close the connection. CookieMode = enabled | disabled | verify Default is disabled. If Cookies are enabled all valid cookies will automatically be -- cgit v1.2.3 From 134eb88158b5ccb49afc054091deea38580e9f86 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Thu, 14 Jun 2012 12:56:25 +0200 Subject: Added missing comma and set proper version --- lib/inets/doc/src/httpc.xml | 105 +++++++++++++++++++++++--------------------- lib/inets/vsn.mk | 2 +- 2 files changed, 55 insertions(+), 52 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index f032ac96e1..f4d3b97122 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -480,66 +480,69 @@ apply(Module, Function, [ReplyInfo | Args]) ex: "134.138" or "[FEDC:BA98" (all IP-addresses starting with 134.138 or FEDC:BA98), "66.35.250.150" or "[2010:836B:4179::836B:4179]" (a complete IP-address). MaxSessions = integer() Default is 2. - Maximum number of persistent connections to a host. + Maximum number of persistent connections to a host. MaxKeepAlive = integer() - Default is 5. - Maximum number of outstanding requests on the same connection to - a host. - KeepAliveTimeout = integer() - Default is 120000 (= 2 min). - If a persistent connection is idle longer than the - keep_alive_timeout in milliseconds, the client will close the connection. - The server may also have such a time out but you should - not count on it! + Default is 5. + Maximum number of outstanding requests on the same connection to + a host. + KeepAliveTimeout = integer() + Default is 120000 (= 2 min). + If a persistent connection is idle longer than the + keep_alive_timeout in milliseconds, + the client will close the connection. + The server may also have such a time out but you should + not count on it! MaxPipeline = integer() - Default is 2. - Maximum number of outstanding requests on a pipelined connection to a host. - PipelineTimeout = integer() - Default is 0, - which will result in pipelining not being used. - If a persistent connection is idle longer than the - pipeline_timeout in milliseconds the client will close the connection. + Default is 2. + Maximum number of outstanding requests on a pipelined connection + to a host. + PipelineTimeout = integer() + Default is 0, + which will result in pipelining not being used. + If a persistent connection is idle longer than the + pipeline_timeout in milliseconds, + the client will close the connection. CookieMode = enabled | disabled | verify Default is disabled. - If Cookies are enabled all valid cookies will automatically be - saved in the client manager's cookie database. - If the option verify is used the function store_cookies/2 - has to be called for the cookies to be saved. - IpFamily = inet | inet6 | inet6fb4 - By default inet. - When it is set to inet6fb4 you can use both ipv4 and ipv6. - It first tries inet6 and if that does not works falls back to inet. - The option is here to provide a workaround for buggy ipv6 stacks to ensure that - ipv4 will always work. + If Cookies are enabled all valid cookies will automatically be + saved in the client manager's cookie database. + If the option verify is used the function store_cookies/2 + has to be called for the cookies to be saved. + IpFamily = inet | inet6 | inet6fb4 + By default inet. + When it is set to inet6fb4 you can use both ipv4 and ipv6. + It first tries inet6 and if that does not works falls back to inet. + The option is here to provide a workaround for buggy ipv6 stacks to ensure that + ipv4 will always work. IpAddress = ip_address() - If the host has several network interfaces, this option specifies which one to use. - See gen_tcp:connect/3,4 for more info. + If the host has several network interfaces, this option specifies which one to use. + See gen_tcp:connect/3,4 for more info. Port = integer() - Specify which local port number to use. - See gen_tcp:connect/3,4 for more info. - VerboseMode = false | verbose | debug | trace - Default is false. - This option is used to switch on (or off) - different levels of erlang trace on the client. - It is a debug feature. + Specify which local port number to use. + See gen_tcp:connect/3,4 for more info. + VerboseMode = false | verbose | debug | trace + Default is false. + This option is used to switch on (or off) + different levels of erlang trace on the client. + It is a debug feature. Profile = profile() | pid() (when started stand_alone) -

Sets options to be used for subsequent requests.

- -

If possible the client will keep its connections - alive and use persistent connections - with or without pipeline depending on configuration - and current circumstances. The HTTP/1.1 specification does not - provide a guideline for how many requests would be - ideal to be sent on a persistent connection, - this very much depends on the - application. Note that a very long queue of requests may cause a - user perceived delay as earlier requests may take a long time - to complete. The HTTP/1.1 specification does suggest a - limit of 2 persistent connections per server, which is the - default value of the max_sessions option.

-
+

Sets options to be used for subsequent requests.

+ +

If possible the client will keep its connections + alive and use persistent connections + with or without pipeline depending on configuration + and current circumstances. The HTTP/1.1 specification does not + provide a guideline for how many requests would be + ideal to be sent on a persistent connection, + this very much depends on the + application. Note that a very long queue of requests may cause a + user perceived delay as earlier requests may take a long time + to complete. The HTTP/1.1 specification does suggest a + limit of 2 persistent connections per server, which is the + default value of the max_sessions option.

+
diff --git a/lib/inets/vsn.mk b/lib/inets/vsn.mk index 488947c3a1..949eceea7f 100644 --- a/lib/inets/vsn.mk +++ b/lib/inets/vsn.mk @@ -18,7 +18,7 @@ # %CopyrightEnd% APPLICATION = inets -INETS_VSN = 5.9 +INETS_VSN = 5.9.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(INETS_VSN)$(PRE_VSN)" -- cgit v1.2.3 From 2fca4419268c38a8c68124786a9dd5c6b0643197 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 10 Jul 2012 16:39:46 +0200 Subject: Fixed pdf text "overflow" problems in the documentation --- lib/snmp/doc/src/snmp_config.xml | 3 ++- lib/snmp/doc/src/snmpa_network_interface_filter.xml | 6 ++++-- lib/snmp/doc/src/snmpm.xml | 14 +++++++------- lib/snmp/doc/src/snmpm_network_interface_filter.xml | 4 +++- 4 files changed, 16 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml index 340f2f1fa7..eec53162a1 100644 --- a/lib/snmp/doc/src/snmp_config.xml +++ b/lib/snmp/doc/src/snmp_config.xml @@ -963,7 +963,8 @@ Manager snmp config: 7b. User name? hobbes 7c. Security name? [hobbes] 7d. Authentication protocol (no/sha/md5)? [no] sha -7e Authentication [sha] key (length 0 or 20)? [""] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] +7e Authentication [sha] key (length 0 or 20)? [""] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \ + 17,18,19,20] 7d. Priv protocol (no/des/aes)? [no] des 7f Priv [des] key (length 0 or 16)? [""] 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 7. Configure an usm user handled by this manager (y/n)? [y] n diff --git a/lib/snmp/doc/src/snmpa_network_interface_filter.xml b/lib/snmp/doc/src/snmpa_network_interface_filter.xml index 10419517dd..84953c5270 100644 --- a/lib/snmp/doc/src/snmpa_network_interface_filter.xml +++ b/lib/snmp/doc/src/snmpa_network_interface_filter.xml @@ -1,4 +1,4 @@ - + @@ -84,7 +84,9 @@ DATA TYPES 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 diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml index 9bbb6cdbdb..8ab3be8e18 100644 --- a/lib/snmp/doc/src/snmpm.xml +++ b/lib/snmp/doc/src/snmpm.xml @@ -173,16 +173,16 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv

Register the manager entity (=user) responsible for specific - agent(s).

+ agent(s).

Module is the callback module (snmpm_user behaviour) which - will be called whenever something happens (detected - agent, incoming reply or incoming trap/notification). - Note that this could have already been done as a - consequence of the node config. (see users.conf).

+ will be called whenever something happens (detected + agent, incoming reply or incoming trap/notification). + Note that this could have already been done as a + consequence of the node config. (see users.conf).

-

The argument DefaultAgentConfig is used as default values when - this user register agents.

+

The argument DefaultAgentConfig is used as default + values when this user register agents.

The type of Val depends on Item:

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(-) (limited to 'lib') 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 6549340d9920df8f8c29223fe1853a37e30f0a41 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 11 Jul 2012 11:07:30 +0200 Subject: [inets] Updated release notes and improved parts of the doc Updated release and improved (httpc-) documentation for KeepAlive and Pipeline timeout options. OTP-10095, OTP-10114 --- lib/inets/doc/src/notes.xml | 110 ++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 56 deletions(-) (limited to 'lib') diff --git a/lib/inets/doc/src/notes.xml b/lib/inets/doc/src/notes.xml index b6e8be467f..437fa7b9d4 100644 --- a/lib/inets/doc/src/notes.xml +++ b/lib/inets/doc/src/notes.xml @@ -13,12 +13,12 @@ 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. - + Inets Release Notes @@ -32,42 +32,37 @@ notes.xml - -

Inets 5.9.1 - -
Improvements and New Features - - + +
+ Inets 5.9.1 + +
+ Improvements and New Features + + - -

Better handling of error(s) during update of the session - database.

-

Also added - (which_sessions/0,1) - and updated and documented - (info/0) - some debugging functions.

-

Own Id: OTP-10093

-

Aux Id: Seq 12062

-
- - -

Removed R14B compatible version of (inets-service and + +

Removed R14B compatible version of (inets-service and tftp) behaviour definition.

Own Id: OTP-10095

-
- + + + +

[httpc] Documentation of KeepAlive and Pipeline timeout + options have been improved.

+

Own Id: OTP-10114

+
- +
-
Fixed Bugs and Malfunctions - - +
+ Fixed Bugs and Malfunctions +

-

+ +
- - +
---> - +
- -
Inets 5.9 - -
Improvements and New Features - - + +
+ Inets 5.9 + +
+ Improvements and New Features + + - +

[httpd] Make the server header configurable with new config option server_tokens. -- cgit v1.2.3 From 84f2859757a7fbf3d1280648f995e0a7d0e0754b Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 18 Jul 2012 12:52:57 +0200 Subject: Add error reason ehostunreach when trying with IPv4 If a IPv6 (inet6) connect fails, we try to connect with IPv4 (inet) again. Added error reason ehostunreach for which it is ok to try again (with IPv4). --- lib/inets/test/inets_test_lib.erl | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl index 7f4b0ec8d8..4ec8a6002f 100644 --- a/lib/inets/test/inets_test_lib.erl +++ b/lib/inets/test/inets_test_lib.erl @@ -536,25 +536,15 @@ connect(ip_comm, Host, Port, Opts, Type) -> tsp("connect success"), {ok, Socket}; - {error, nxdomain} when Type =:= inet6 -> - tsp("connect error nxdomain when" - "~n Opts: ~p", [Opts]), - connect(ip_comm, Host, Port, Opts -- [inet6], inet); - {error, eafnosupport} when Type =:= inet6 -> - tsp("connect error eafnosupport when" - "~n Opts: ~p", [Opts]), - connect(ip_comm, Host, Port, Opts -- [inet6], inet); - {error, econnreset} when Type =:= inet6 -> - tsp("connect error econnreset when" - "~n Opts: ~p", [Opts]), - connect(ip_comm, Host, Port, Opts -- [inet6], inet); - {error, enetunreach} when Type =:= inet6 -> - tsp("connect error eafnosupport when" - "~n Opts: ~p", [Opts]), - connect(ip_comm, Host, Port, Opts -- [inet6], inet); - {error, econnrefused} when Type =:= inet6 -> - tsp("connect error econnrefused when" - "~n Opts: ~p", [Opts]), + {error, Reason} when ((Type =:= inet6) andalso + ((Reason =:= nxdomain) orelse + (Reason =:= eafnosupport) orelse + (Reason =:= econnreset) orelse + (Reason =:= enetunreach) orelse + (Reason =:= econnrefused) orelse + (Reason =:= ehostunreach))) -> + tsp("connect error ~w when" + "~n Opts: ~p", [Reason, Opts]), connect(ip_comm, Host, Port, Opts -- [inet6], inet); Error -> -- cgit v1.2.3 From 3d639df53de38e398a208f4f57cc9a7969733c63 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Fri, 20 Jul 2012 10:14:09 +0200 Subject: Improved debug printouts --- lib/inets/test/inets_test_lib.erl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl index 4ec8a6002f..ef6529025f 100644 --- a/lib/inets/test/inets_test_lib.erl +++ b/lib/inets/test/inets_test_lib.erl @@ -543,12 +543,14 @@ connect(ip_comm, Host, Port, Opts, Type) -> (Reason =:= enetunreach) orelse (Reason =:= econnrefused) orelse (Reason =:= ehostunreach))) -> - tsp("connect error ~w when" - "~n Opts: ~p", [Reason, Opts]), + tsp("connect(ip_comm) -> Connect error: " + "~n Reason: ~p" + "~n Type: ~p" + "~n Opts: ~p", [Reason, Type, Opts]), connect(ip_comm, Host, Port, Opts -- [inet6], inet); Error -> - tsp("connect(ip_conn) -> Fatal connect error: " + tsp("connect(ip_comm) -> Fatal connect error: " "~n Error: ~p" "~nwhen" "~n Host: ~p" -- cgit v1.2.3 From 3f61f4daccc11658e838771b696c205fccac709e Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 24 Jul 2012 12:57:20 +0200 Subject: Add connect timeout --- lib/inets/test/inets_test_lib.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl index ef6529025f..e7c44391c7 100644 --- a/lib/inets/test/inets_test_lib.erl +++ b/lib/inets/test/inets_test_lib.erl @@ -531,7 +531,7 @@ connect(ip_comm, Host, Port, Opts, Type) -> "~n Opts: ~p" "~n Type: ~p", [Host, Port, Opts, Type]), - case gen_tcp:connect(Host, Port, Opts) of + case gen_tcp:connect(Host, Port, Opts, timer:seconds(10)) of {ok, Socket} -> tsp("connect success"), {ok, Socket}; -- cgit v1.2.3 From 5031e2277c1b1af83bde2d3990d2fc4ab3f119c5 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Wed, 25 Jul 2012 08:46:36 +0200 Subject: Did not handle timeout reason when IPv6 --- lib/inets/test/inets_test_lib.erl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/inets/test/inets_test_lib.erl b/lib/inets/test/inets_test_lib.erl index e7c44391c7..0f8671b682 100644 --- a/lib/inets/test/inets_test_lib.erl +++ b/lib/inets/test/inets_test_lib.erl @@ -537,7 +537,8 @@ connect(ip_comm, Host, Port, Opts, Type) -> {ok, Socket}; {error, Reason} when ((Type =:= inet6) andalso - ((Reason =:= nxdomain) orelse + ((Reason =:= timeout) orelse + (Reason =:= nxdomain) orelse (Reason =:= eafnosupport) orelse (Reason =:= econnreset) orelse (Reason =:= enetunreach) orelse -- cgit v1.2.3 From 4a7c3d856148c447f07150d86f04f078c82be33f Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 30 Jul 2012 13:52:26 +0200 Subject: [inets/httpd] Add prinouts to the security test case --- lib/inets/test/httpd_mod.erl | 229 ++++++++++++++++++++++++++++++++----------- 1 file changed, 173 insertions(+), 56 deletions(-) (limited to 'lib') diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl index cb1214b7fb..b548eba6b7 100644 --- a/lib/inets/test/httpd_mod.erl +++ b/lib/inets/test/httpd_mod.erl @@ -82,19 +82,23 @@ actions(Type, Port, Host, Node) -> [{statuscode, 200}, {version, "HTTP/1.0"}]). + %%------------------------------------------------------------------------- security(ServerRoot, Type, Port, Host, Node) -> - %% io:format(user, "~w:security -> entry with" - %% "~n ServerRoot: ~p" - %% "~n Type: ~p" - %% "~n Port: ~p" - %% "~n Host: ~p" - %% "~n Node: ~p" - %% "~n", [?MODULE, ServerRoot, Type, Port, Host, Node]), - -%% io:format(user, "~w:security -> register~n", [?MODULE]), + tsp("security -> " + "entry with" + "~n ServerRoot: ~p" + "~n Type: ~p" + "~n Port: ~p" + "~n Host: ~p" + "~n Node: ~p", [ServerRoot, Type, Port, Host, Node]), + + tsp("security -> " + "register - receive security events"), global:register_name(mod_security_test, self()), % Receive events + tsp("security -> " + "sleep"), test_server:sleep(5000), OpenDir = filename:join([ServerRoot, "htdocs", "open"]), @@ -102,133 +106,240 @@ security(ServerRoot, Type, Port, Host, Node) -> %% Test blocking / unblocking of users. %% /open, require user one Aladdin -%% io:format(user, "~w:security -> remove user~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "remove all existing users"), remove_users(Node, ServerRoot, Host, Port, "open"), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for nonex user 'one' - expect 401"), auth_request(Type, Host, Port, Node, "/open/", "one", "onePassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "one"}, {password, "onePassword"}]}, Node, Port), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for nonex user 'two' - expect 401"), auth_request(Type,Host,Port,Node,"/open/", "two", "twoPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "two"}, {password, "twoPassword"}]}, Node, Port), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for nonex user 'Alladin' - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "Aladdin", "AladdinPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "Aladdin"}, {password, "AladdinPassword"}]}, Node, Port), -%% io:format(user, "~w:security -> add users~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "add user 'one'"), add_user(Node, ServerRoot, Port, "open", "one", "onePassword", []), + + tsp("security -> " + "blocking and unblocking of users - " + "add user 'two'"), add_user(Node, ServerRoot, Port, "open", "two", "twoPassword", []), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request 1 for user 'one' with wrong password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "one"}, {password, "WrongPassword"}]}, Node, Port), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request 2 for user 'one' with wrong password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> await fail security event~n", [?MODULE]), + + tsp("security -> " + "blocking and unblocking of users - " + "await fail security event"), receive_security_event({event, auth_fail, Port, OpenDir, [{user, "one"}, {password, "WrongPassword"}]}, Node, Port), -%% io:format(user, "~w:security -> await block security event~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "await block security event (two failed attempts)"), receive_security_event({event, user_block, Port, OpenDir, [{user, "one"}]}, Node, Port), -%% io:format(user, "~w:security -> unregister~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "unregister - no more security events"), global:unregister_name(mod_security_test), % No more events. -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for user 'one' with wrong password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "one", "WrongPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "auth request for user 'one' with correct password - expect 403"), auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword", [{statuscode, 403}]), %% User "one" should be blocked now.. - %% [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node,Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "list blocked users - 'one' should be the only one"), case list_blocked_users(Node, Port) of [{"one",_, Port, OpenDir,_}] -> ok; Blocked -> - %% io:format(user, "~w:security -> Blocked: ~p" - %% "~n", [?MODULE, Blocked]), + tsp(" *** unexpected blocked users ***" + "~n Blocked: ~p", [Blocked]), exit({unexpected_blocked, Blocked}) end, - -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), - [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node,Port,OpenDir), -%% io:format(user, "~w:security -> unblock user~n", [?MODULE]), + tsp("security -> " + "blocking and unblocking of users - " + "list users blocked for dir '~p' - " + "user 'one' should be the only one", [OpenDir]), + [{"one",_, Port, OpenDir,_}] = list_blocked_users(Node, Port, OpenDir), + + tsp("security -> " + "blocking and unblocking of users - " + "unblock user 'one' for dir '~p'", [OpenDir]), true = unblock_user(Node, "one", Port, OpenDir), - %% User "one" should not be blocked any more.. -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + %% User "one" should not be blocked any more. + + tsp("security -> " + "blocking and unblocking of users - " + "ensure user 'one' is no longer blocked"), [] = list_blocked_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), - [] = list_blocked_users(Node, Port, OpenDir), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + + + tsp("security -> " + "blocking and unblocking of users - " + "auth request for user 'one' with correct password - expect 200"), auth_request(Type, Host, Port, Node,"/open/", "one", "onePassword", [{statuscode, 200}]), + + %% Test list_auth_users & auth_timeout -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users - expect user 'one'"), ["one"] = list_auth_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), - ["one"] = list_auth_users(Node, Port, OpenDir), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "auth request for user 'two' with wrong password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "two", "onePassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users - expect user 'one'"), ["one"] = list_auth_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users for dir '~p' - expect user 'one'", [OpenDir]), ["one"] = list_auth_users(Node, Port, OpenDir), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "auth request for user 'two' with correct password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword", [{statuscode, 401}]), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users - expect user 'one'"), ["one"] = list_auth_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users for dir '~p' - expect user 'one'", [OpenDir]), ["one"] = list_auth_users(Node, Port, OpenDir), + %% Wait for successful auth to timeout. + tsp("security -> " + "list-auth-users and auth-timeout - " + "wait for successful auth to timeout"), test_server:sleep(?AUTH_TIMEOUT*1001), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users - expect none"), [] = list_auth_users(Node, Port), -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "list auth users for dir '~p'~n - expect none", [OpenDir]), [] = list_auth_users(Node, Port, OpenDir), + %% "two" is blocked. -%% io:format(user, "~w:security -> unblock user~n", [?MODULE]), + + tsp("security -> " + "list-auth-users and auth-timeout - " + "unblock user 'two' for dir '~p'", [OpenDir]), true = unblock_user(Node, "two", Port, OpenDir), + + %% Test explicit blocking. Block user 'two'. -%% io:format(user, "~w:security -> list blocked users~n", [?MODULE]), + + tsp("security -> " + "explicit blocking - list blocked users - should be none"), [] = list_blocked_users(Node,Port,OpenDir), -%% io:format(user, "~w:security -> block user~n", [?MODULE]), + + tsp("security -> " + "explicit blocking - " + "block user 'two' for dir '~p'", [OpenDir]), true = block_user(Node, "two", Port, OpenDir, 10), -%% io:format(user, "~w:security -> auth request~n", [?MODULE]), + + tsp("security -> " + "explicit blocking - " + "auth request for user 'two' with correct password - expect 401"), auth_request(Type, Host, Port, Node,"/open/", "two", "twoPassword", - [{statuscode, 401}]). + [{statuscode, 401}]), + tsp("security -> " + "done"). + %%------------------------------------------------------------------------- auth(Type, Port, Host, Node) -> + tsp("auth -> " + "entry with" + "~n Type: ~p" + "~n Port: ~p" + "~n Host: ~p" + "~n Node: ~p", [Type, Port, Host, Node]), + %% Authentication required! ok = httpd_test_lib:verify_request(Type,Host,Port,Node, "GET /open/ HTTP/1.0\r\n\r\n", @@ -1027,8 +1138,14 @@ check_lists_members1(L1,L2) -> {error,{lists_not_equal,L1,L2}}. -%% tsp(F) -> -%% inets_test_lib:tsp(F). +%% p(F) -> +%% p(F, []). + +%% p(F, A) -> +%% io:format(user, "~w:" ++ F ++ "~n", [?MODULE|A]). + +tsp(F) -> + inets_test_lib:tsp(F). tsp(F, A) -> inets_test_lib:tsp(F, A). -- 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(-) (limited to 'lib') 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(-) (limited to 'lib') 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(-) (limited to 'lib') 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(-) (limited to 'lib') 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(-) (limited to 'lib') 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(-) (limited to 'lib') 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(-) (limited to 'lib') 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(+) (limited to 'lib') 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(-) (limited to 'lib') 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(-) (limited to 'lib') 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(-) (limited to 'lib') 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 From c41d2c6490f7060989bcdbfe741061f0dc38efa3 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 10 Jul 2012 16:39:46 +0200 Subject: [snmp] Fixed pdf text "overflow" problems in the documentation --- lib/snmp/doc/src/snmp_config.xml | 3 ++- lib/snmp/doc/src/snmpa_network_interface_filter.xml | 6 ++++-- lib/snmp/doc/src/snmpm.xml | 14 +++++++------- lib/snmp/doc/src/snmpm_network_interface_filter.xml | 4 +++- 4 files changed, 16 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml index 340f2f1fa7..eec53162a1 100644 --- a/lib/snmp/doc/src/snmp_config.xml +++ b/lib/snmp/doc/src/snmp_config.xml @@ -963,7 +963,8 @@ Manager snmp config: 7b. User name? hobbes 7c. Security name? [hobbes] 7d. Authentication protocol (no/sha/md5)? [no] sha -7e Authentication [sha] key (length 0 or 20)? [""] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] +7e Authentication [sha] key (length 0 or 20)? [""] [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, \ + 17,18,19,20] 7d. Priv protocol (no/des/aes)? [no] des 7f Priv [des] key (length 0 or 16)? [""] 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 7. Configure an usm user handled by this manager (y/n)? [y] n diff --git a/lib/snmp/doc/src/snmpa_network_interface_filter.xml b/lib/snmp/doc/src/snmpa_network_interface_filter.xml index 10419517dd..84953c5270 100644 --- a/lib/snmp/doc/src/snmpa_network_interface_filter.xml +++ b/lib/snmp/doc/src/snmpa_network_interface_filter.xml @@ -1,4 +1,4 @@ - + @@ -84,7 +84,9 @@ DATA TYPES 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

diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml index 9bbb6cdbdb..8ab3be8e18 100644 --- a/lib/snmp/doc/src/snmpm.xml +++ b/lib/snmp/doc/src/snmpm.xml @@ -173,16 +173,16 @@ sec_level() = noAuthNoPriv | authNoPriv | authPriv

Register the manager entity (=user) responsible for specific - agent(s).

+ agent(s).

Module is the callback module (snmpm_user behaviour) which - will be called whenever something happens (detected - agent, incoming reply or incoming trap/notification). - Note that this could have already been done as a - consequence of the node config. (see users.conf).

+ will be called whenever something happens (detected + agent, incoming reply or incoming trap/notification). + Note that this could have already been done as a + consequence of the node config. (see users.conf).

-

The argument DefaultAgentConfig is used as default values when - this user register agents.

+

The argument DefaultAgentConfig is used as default + values when this user register agents.

The type of Val depends on Item:

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 db929c5aacb412eb94fbe0757a47a41564e6fb51 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Tue, 10 Jul 2012 16:45:43 +0200 Subject: [snmp] 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(-) (limited to 'lib') 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 3cdb7781aca3cfff24485f7a9dbe704a4824d5e1 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 13 Aug 2012 14:42:00 +0200 Subject: [snmp] Add bug compatible fixes to TimeTicks decode Add handling of incorrectly encoded TimeTicks and Unsigned32. --- lib/snmp/src/misc/snmp_pdus.erl | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'lib') diff --git a/lib/snmp/src/misc/snmp_pdus.erl b/lib/snmp/src/misc/snmp_pdus.erl index e15be4a298..5b8be90a71 100644 --- a/lib/snmp/src/misc/snmp_pdus.erl +++ b/lib/snmp/src/misc/snmp_pdus.erl @@ -298,22 +298,30 @@ dec_value([65 | Bytes]) -> %% Unsigned32 dec_value([66 | Bytes]) -> {Value, Rest} = dec_integer_notag(Bytes), - if - (Value >= 0) andalso (Value =< 16#ffffffff) -> - {{'Unsigned32', Value}, Rest}; - true -> - exit({error, {bad_unsigned32, Value}}) - end; + Value2 = + if + (Value >= 0) andalso (Value =< 16#ffffffff) -> + Value; + (Value < 0) -> + 16#ffffffff + Value + 1; + true -> + exit({error, {bad_unsigned32, Value}}) + end, + {{'Unsigned32', Value2}, Rest}; %% TimeTicks dec_value([67 | Bytes]) -> {Value, Rest} = dec_integer_notag(Bytes), - if - (Value >= 0) andalso (Value =< 16#ffffffff) -> - {{'TimeTicks', Value}, Rest}; + Value2 = + if + (Value >= 0) andalso (Value =< 16#ffffffff) -> + Value; + (Value < 0) -> + 16#ffffffff + Value + 1; true -> exit({error, {bad_timeticks, Value}}) - end; + end, + {{'TimeTicks', Value2}, Rest}; %% Opaque dec_value([68 | Bytes]) -> -- cgit v1.2.3 From d8633aded52b5dc96707667cca72ef632e414296 Mon Sep 17 00:00:00 2001 From: Micael Karlberg Date: Mon, 30 Jul 2012 14:38:13 +0200 Subject: [inets/httpd] Add another (cosmetic) printout for security test case --- lib/inets/test/httpd_mod.erl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'lib') diff --git a/lib/inets/test/httpd_mod.erl b/lib/inets/test/httpd_mod.erl index b548eba6b7..387263ce58 100644 --- a/lib/inets/test/httpd_mod.erl +++ b/lib/inets/test/httpd_mod.erl @@ -1024,13 +1024,11 @@ list_users(Node, Root, _Host, Port, Dir) -> receive_security_event(Event, Node, Port) -> - %% io:format(user, "~w:receive_security_event -> entry with" - %% "~n Event: ~p" - %% "~n Node: ~p" - %% "~n Port: ~p" - %% "~n", [?MODULE, Event, Node, Port]), + tsp("receive_security_event -> await ~w event", [element(2, Event)]), receive Event -> + tsp("receive_security_event -> " + "received expected ~w event", [element(2, Event)]), ok; {'EXIT', _, _} -> receive_security_event(Event, Node, Port) -- cgit v1.2.3