From 215b2305cad4f1bc45fd33677198e3887d200869 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Fri, 8 Aug 2014 10:04:55 +0200 Subject: Rewrite manager net_if for IPv4+IPv6 --- lib/snmp/src/manager/snmpm_conf.erl | 1 + lib/snmp/src/manager/snmpm_config.erl | 372 ++++++-------------------- lib/snmp/src/manager/snmpm_net_if.erl | 490 +++++++++++++++++++++------------- lib/snmp/src/misc/snmp_config.erl | 40 ++- 4 files changed, 412 insertions(+), 491 deletions(-) diff --git a/lib/snmp/src/manager/snmpm_conf.erl b/lib/snmp/src/manager/snmpm_conf.erl index 888f19aec6..e03d28a3e4 100644 --- a/lib/snmp/src/manager/snmpm_conf.erl +++ b/lib/snmp/src/manager/snmpm_conf.erl @@ -114,6 +114,7 @@ do_write_manager_conf(Fd, {Tag, Val}) when Tag =:= domain; Tag =:= address; Tag =:= port; + Tag =:= transports; Tag =:= max_message_size -> io:format(Fd, "{~w, ~w}.~n", [Tag, Val]); do_write_manager_conf(Fd, {Tag, Val}) diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 013fefa4e2..d147aabb0b 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -1287,36 +1287,6 @@ verify_options(Opts, Mandatory) -> verify_mandatory_options(Opts, Mandatory), verify_options(Opts). -%% mandatory() -> [mand()] -%% mand() -> atom() | {atom, [atom()]} -verify_mandatory_options(_Opts, []) -> - ok; -verify_mandatory_options(Opts, [Mand|Mands]) -> - verify_mandatory_option(Opts, Mand), - verify_mandatory_options(Opts, Mands). - -verify_mandatory_option(Opts, {Mand, MandSubOpts}) -> - ?d("verify_mandatory_option -> entry with" - "~n Mand: ~p" - "~n MandSubObjs: ~p", [Mand, MandSubOpts]), - case lists:keysearch(Mand, 1, Opts) of - {value, {Mand, SubOpts}} -> - verify_mandatory_options(SubOpts, MandSubOpts); - false -> - ?d("missing mandatory option: ~w [~p]", [Mand, MandSubOpts]), - error({missing_mandatory, Mand, MandSubOpts}) - end; -verify_mandatory_option(Opts, Mand) -> - ?d("verify_mandatory_option -> entry with" - "~n Mand: ~p", [Mand]), - case lists:keymember(Mand, 1, Opts) of - true -> - ok; - false -> - ?d("missing mandatory option: ~w", [Mand]), - error({missing_mandatory, Mand}) - end. - verify_options([]) -> ?d("verify_options -> done", []), ok; @@ -1632,7 +1602,38 @@ verify_verbosity(Verbosity) -> _ -> error({invalid_verbosity, Verbosity}) end. + +%% mandatory() -> [mand()] +%% mand() -> atom() | {atom, [atom()]} +verify_mandatory_options(_Opts, []) -> + ok; +verify_mandatory_options(Opts, [Mand|Mands]) -> + verify_mandatory_option(Opts, Mand), + verify_mandatory_options(Opts, Mands). + +verify_mandatory_option(Opts, {Mand, MandSubOpts}) -> + ?d("verify_mandatory_option -> entry with" + "~n Mand: ~p" + "~n MandSubObjs: ~p", [Mand, MandSubOpts]), + case lists:keysearch(Mand, 1, Opts) of + {value, {Mand, SubOpts}} -> + verify_mandatory_options(SubOpts, MandSubOpts); + false -> + ?d("missing mandatory option: ~w [~p]", [Mand, MandSubOpts]), + error({missing_mandatory, Mand, MandSubOpts}) + end; +verify_mandatory_option(Opts, Mand) -> + ?d("verify_mandatory_option -> entry with" + "~n Mand: ~p", [Mand]), + case lists:keymember(Mand, 1, Opts) of + true -> + ok; + false -> + ?d("missing mandatory option: ~w", [Mand]), + error({missing_mandatory, Mand}) + end. + %% ------------------------------------------------------------------------ init_manager_config([]) -> @@ -1654,69 +1655,10 @@ init_agent_default() -> {version, v2}, % MPModel {sec_model, v2c}, % SecModel {sec_name, "initial"}, % SecName - {sec_level, noAuthPriv}, % SecLevel + {sec_level, noAuthNoPriv}, % SecLevel {community, "all-rights"}], % Community do_update_agent_info(default_agent, AgentDefaultConfig). -%% %% Port -%% init_agent_default(port, ?DEFAULT_AGENT_PORT), - -%% %% Timeout -%% init_agent_default(timeout, 10000), - -%% %% Max message (packet) size -%% init_agent_default(max_message_size, 484), - -%% %% MPModel -%% init_agent_default(version, v2), - -%% %% SecModel -%% init_agent_default(sec_model, v2c), - -%% %% SecName -%% init_agent_default(sec_name, "initial"), - -%% %% SecLevel -%% init_agent_default(sec_level, noAuthNoPriv), - -%% %% Community -%% init_agent_default(community, "all-rights"), -%% ok. - - -%% init_agent_default(Item, Val) when Item =/= user_id -> -%% case do_update_agent_info(default_agent, Item, Val) of -%% ok -> -%% ok; -%% {error, Reason} -> -%% error(Reason) -%% end. - -%% read_agents_config_file(Dir) -> -%% Verify = fun check_agent_config2/1, -%% case read_file(Dir, "agents.conf", Verify, []) of -%% {ok, Conf} -> -%% Conf; -%% Error -> -%% ?vlog("agent config error: ~p", [Error]), -%% throw(Error) -%% end. - -%% check_agent_config2(Agent) -> -%% case (catch check_agent_config(Agent)) of -%% {ok, {UserId, TargetName, Conf, Version}} -> -%% {ok, Vsns} = system_info(versions), -%% case lists:member(Version, Vsns) of -%% true -> -%% {ok, {UserId, TargetName, Conf}}; -%% false -> -%% error({version_not_supported_by_manager, -%% Version, Vsns}) -%% end; -%% Err -> -%% throw(Err) -%% end. - read_agents_config_file(Dir) -> Order = fun snmp_conf:no_order/2, Check = fun check_agent_config/2, @@ -1738,12 +1680,20 @@ check_agent_config(Agent, State) -> end. %% For backward compatibility +check_agent_config( + {UserId, TargetName, Community, Domain, Addr, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel}) when is_atom(Domain) -> + check_agent_config( + UserId, TargetName, Community, Domain, Addr, + EngineId, Timeout, MaxMessageSize, + Version, SecModel, SecName, SecLevel); check_agent_config( {UserId, TargetName, Community, Ip, Port, EngineId, Timeout, MaxMessageSize, - Version, SecModel, SecName, SecLevel}) -> + Version, SecModel, SecName, SecLevel}) when is_integer(Port) -> Domain = default_transport_domain(), - Addr = fix_address(Domain, {Ip, Port}), + Addr = {Ip, Port}, check_agent_config( UserId, TargetName, Community, Domain, Addr, EngineId, Timeout, MaxMessageSize, @@ -1752,8 +1702,9 @@ check_agent_config( {UserId, TargetName, Community, Domain, Ip, Port, EngineId, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel}) -> + Addr = {Ip, Port}, check_agent_config( - UserId, TargetName, Community, Domain, {Ip, Port}, + UserId, TargetName, Community, Domain, Addr, EngineId, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel); check_agent_config(Agent) -> @@ -1776,7 +1727,7 @@ check_agent_config( Conf = [{reg_type, target_name}, {tdomain, Domain}, - {taddress, Addr}, + {taddress, fix_address(Domain, Addr)}, {community, Comm}, {engine_id, EngineId}, {timeout, Timeout}, @@ -1946,16 +1897,6 @@ verify_agent_entry(Item, _) -> -%% read_users_config_file(Dir) -> -%% Verify = fun check_user_config/1, -%% case read_file(Dir, "users.conf", Verify, []) of -%% {ok, Conf} -> -%% Conf; -%% Error -> -%% ?vlog("failure reading users config file: ~n ~p", [Error]), -%% throw(Error) -%% end. - read_users_config_file(Dir) -> Order = fun snmp_conf:no_order/2, Check = fun (User, State) -> {check_user_config(User), State} end, @@ -2074,14 +2015,6 @@ verify_default_agent_config(Conf) -> error({bad_default_agent_config, Error}) end. -%% read_usm_config_file(Dir) -> -%% Verify = fun check_usm_user_config/1, -%% case read_file(Dir, "usm.conf", Verify, []) of -%% {ok, Conf} -> -%% Conf; -%% Error -> -%% throw(Error) -%% end. read_usm_config_file(Dir) -> Order = fun snmp_conf:no_order/2, @@ -2268,24 +2201,6 @@ is_crypto_supported(Func) -> snmp_misc:is_crypto_supported(Func). -%% read_manager_config_file(Dir) -> -%% Verify = fun check_manager_config/1, -%% case read_file(Dir, "manager.conf", Verify) of -%% {ok, Conf} -> -%% ?d("read_manager_config_file -> ok: " -%% "~n Conf: ~p", [Conf]), -%% %% If the address is not specified, then we assume -%% %% it should be the local host. -%% %% If the address is not possible to determine -%% %% that way, then we give up... -%% verify_mandatory(Conf, [port,engine_id,max_message_size]), -%% ensure_config(default_manager_config(), Conf); -%% %% check_mandatory_manager_config(Conf), -%% %% ensure_manager_config(Conf); -%% Error -> -%% throw(Error) -%% end. - read_manager_config_file(Dir) -> Order = fun order_manager_config/2, Check = fun check_manager_config/2, @@ -2296,13 +2211,15 @@ read_manager_config_file(Dir) -> %% it should be the local host. %% If the address is not possible to determine %% that way, then we give up... - verify_mandatory(Conf, [port,engine_id,max_message_size]), + verify_someof(Conf, [port, transports]), + verify_mandatory(Conf, [engine_id, max_message_size]), default_manager_config(Conf). default_manager_config(Conf) -> - %% Ensure address of right family - case lists:keyfind(address, 1, Conf) of + %% Ensure valid transports entry + case lists:keyfind(transports, 1, Conf) of false -> + {port, Port} = lists:keyfind(port, 1, Conf), Domain = case lists:keyfind(domain, 1, Conf) of false -> @@ -2311,55 +2228,55 @@ default_manager_config(Conf) -> D end, Family = snmp_conf:tdomain_to_family(Domain), - {ok, HostName} = inet:gethostname(), - case inet:getaddr(HostName, Family) of + {ok, Hostname} = inet:gethostname(), + case inet:getaddr(Hostname, Family) of {ok, Address} -> - [{address, Address} | Conf]; + lists:sort( + fun order_manager_config/2, + [{transports, [{Domain, {Address, Port}}]} | Conf]); {error, _Reason} -> ?d("default_manager_config -> " "failed getting ~w address for ~s:~n" - " _Reason: ~p", [Family, HostName, _Reason]), + " _Reason: ~p", [Family, Hostname, _Reason]), Conf end; _ -> Conf end. -default_manager_config() -> - {ok, HostName} = inet:gethostname(), - case inet:getaddr(HostName, inet) of - {ok, A} -> - [{address, tuple_to_list(A)}]; - {error, _Reason} -> - ?d("default_manager_config -> failed getting address: " - "~n _Reason: ~p", [_Reason]), - [] - end. - order_manager_config(EntryA, EntryB) -> - snmp_conf:keyorder(1, EntryA, EntryB, [domain]). - -check_manager_config({domain, D}, _Domain) -> - {snmp_conf:check_domain(D), D}; -check_manager_config({address = Tag, Ip}, D) -> - Domain = - case D of - undefined -> - default_transport_domain(); - _ -> - D - end, + snmp_conf:keyorder(1, EntryA, EntryB, [domain, port]). + +check_manager_config(Entry, undefined) -> + check_manager_config(Entry, {default_transport_domain(), undefined}); +check_manager_config({domain, Domain}, {_, Port}) -> + {snmp_conf:check_domain(Domain), {Domain, Port}}; +check_manager_config({port, Port}, {Domain, _}) -> + {ok = snmp_conf:check_port(Port), {Domain, Port}}; +check_manager_config({address, _}, {_, undefined}) -> + error({missing_mandatory, port}); +check_manager_config({address = Tag, Ip} = Entry, {Domain, Port} = State) -> {case snmp_conf:check_ip(Domain, Ip) of ok -> - ok; + [Entry, + {transports, [{Domain, {Ip, Port}}]}]; {ok, FixedIp} -> - {ok, {Tag, FixedIp}} - end, Domain}; -check_manager_config(Entry, Domain) -> - {check_manager_config(Entry), Domain}. + [{Tag, FixedIp}, + {transports, [{Domain, {FixedIp, Port}}]}] + end, State}; +check_manager_config({transports = Tag, Transports}, State) -> + CheckedTransports = + [case snmp_conf:check_address(Domain, Address) of + ok -> + Transport; + {ok, FixedAddress} -> + {Domain, FixedAddress} + end + || {Domain, Address} = Transport <- Transports], + {{ok, {Tag, CheckedTransports}}, State}; +check_manager_config(Entry, State) -> + {check_manager_config(Entry), State}. -check_manager_config({port, Port}) -> - snmp_conf:check_port(Port); check_manager_config({engine_id, EngineID}) -> snmp_conf:check_string(EngineID); check_manager_config({max_message_size, Max}) -> @@ -2368,45 +2285,6 @@ check_manager_config(Conf) -> error({unknown_config, Conf}). -%% check_mandatory_manager_config(Conf) -> -%% Mand = [port, engine_id, max_message_size], -%% check_mandatory_manager_config(Mand, Conf). - -%% check_mandatory_manager_config([], _Conf) -> -%% ok; -%% check_mandatory_manager_config([Item|Mand], Conf) -> -%% case lists:keysearch(Item, 1, Conf) of -%% false -> -%% error({missing_mandatory_manager_config, Item}); -%% _ -> -%% check_mandatory_manager_config(Mand, Conf) -%% end. - - -%% ensure_manager_config(Confs) -> -%% ensure_manager_config(Confs, default_manager_config()). - -%% ensure_manager_config(Confs, []) -> -%% Confs; -%% ensure_manager_config(Confs, [{Key,_} = DefKeyVal|Defs]) -> -%% case lists:keysearch(Key, 1, Confs) of -%% false -> -%% ensure_manager_config([DefKeyVal|Confs], Defs); -%% {value, _Conf} -> -%% ensure_manager_config(Confs, Defs) -%% end. - -% ensure_manager_config([], Defs, Confs) -> -% Confs ++ Defs; -% ensure_manager_config(Confs0, [{Key, DefVal}|Defs], Acc) -> -% case lists:keysearch(Key, 1, Confs0) of -% false -> -% ensure_manager_config(Confs0, Defs, [{Key, DefVal}|Acc]); -% {value, Conf} -> -% Confs = lists:keydelete(Key, 1, Confs0), -% ensure_manager_config(Confs, Defs, [Conf|Acc]) -% end. - read_file(Dir, FileName, Order, Check, Default) -> try snmp_conf:read(filename:join(Dir, FileName), Order, Check) catch @@ -2424,87 +2302,6 @@ read_file(Dir, FileName, Order, Check) -> erlang:raise(throw, Error, erlang:get_stacktrace()) end. - - - - - -%% read_file(Dir, FileName, Verify, Default) -> -%% File = filename:join(Dir, FileName), -%% case file:read_file_info(File) of -%% {ok, _} -> -%% read_file(File, Verify); -%% {error, Reason} -> -%% ?vlog("failed reading config from ~s: ~p", [FileName, Reason]), -%% {ok, Default} -%% end. - -%% read_file(Dir, FileName, Verify) -> -%% File = filename:join(Dir, FileName), -%% case file:read_file_info(File) of -%% {ok, _} -> -%% read_file(File, Verify); -%% {error, Reason} -> -%% error_msg("failed reading config from ~s: ~p", [FileName, Reason]), -%% {error, {failed_reading, FileName, Reason}} -%% end. - -%% read_file(File, Verify) -> -%% Check = fun (Config, State) -> {Verify(Config), State} end, -%% try snmp_conf:read(File, Check) of -%% Conf -> -%% ?vtrace("read_file -> read ok" -%% "~n Conf: ~p", [Conf]), -%% {ok, Conf} -%% catch -%% Error -> -%% ?vtrace("read_file -> read failed:" -%% "~n Error: ~p", [Error]), -%% Error -%% end. - -%% XXX remove - -%% read_file(Dir, FileName, Check, Default) -> -%% File = filename:join(Dir, FileName), -%% case file:read_file_info(File) of -%% {ok, _} -> -%% case (catch do_read(File, Check)) of -%% {ok, Conf} -> -%% {ok, Conf}; -%% Error -> -%% ?vtrace("read_file -> read failed:" -%% "~n Error: ~p", [Error]), -%% Error -%% end; -%% {error, Reason} -> -%% ?vlog("failed reading config from ~s: ~p", [FileName, Reason]), -%% {ok, Default} -%% end. - -%% read_file(Dir, FileName, Check) -> -%% File = filename:join(Dir, FileName), -%% case file:read_file_info(File) of -%% {ok, _} -> -%% case (catch do_read(File, Check)) of -%% {ok, Conf} -> -%% ?vtrace("read_file -> read ok" -%% "~n Conf: ~p", [Conf]), -%% {ok, Conf}; -%% Error -> -%% ?vtrace("read_file -> read failed:" -%% "~n Error: ~p", [Error]), -%% Error -%% end; -%% {error, Reason} -> -%% error_msg("failed reading config from ~s: ~p", [FileName, Reason]), -%% {error, {failed_reading, FileName, Reason}} -%% end. - -%% do_read(File, Check) -> -%% {ok, snmp_conf:read(File, Check)}. - - %%-------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | @@ -3582,4 +3379,3 @@ error_msg(F, A) -> p(F, A) -> io:format("~w:" ++ F ++ "~n", [?MODULE | A]). - diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl index 860b0b83dd..c4716dfd21 100644 --- a/lib/snmp/src/manager/snmpm_net_if.erl +++ b/lib/snmp/src/manager/snmpm_net_if.erl @@ -59,8 +59,9 @@ { server, note_store, - domain, - sock, +%% domain, +%% sock, + transports = [], mpd_state, log, irb = auto, % auto | {user, integer()} @@ -68,6 +69,9 @@ filter }). +-record(transport, + {socket, + domain = snmpUDPDomain}). -define(DEFAULT_FILTER_MODULE, snmpm_net_if_filter). -define(DEFAULT_FILTER_OPTS, [{module, ?DEFAULT_FILTER_MODULE}]). @@ -161,12 +165,17 @@ init([Server, NoteStore]) -> ?d("init -> entry with" "~n Server: ~p" "~n NoteStore: ~p", [Server, NoteStore]), - case (catch do_init(Server, NoteStore)) of + try do_init(Server, NoteStore) + catch {error, Reason} -> - {stop, Reason}; - {ok, State} -> - {ok, State} + {stop, Reason} end. + %% case (catch do_init(Server, NoteStore)) of + %% {error, Reason} -> + %% {stop, Reason}; + %% {ok, State} -> + %% {ok, State} + %% end. do_init(Server, NoteStore) -> process_flag(trap_exit, true), @@ -196,21 +205,6 @@ do_init(Server, NoteStore) -> {ok, IRB} = snmpm_config:system_info(net_if_irb), IrGcRef = irgc_start(IRB), - %% -- Socket -- - SndBuf = get_opt(Opts, sndbuf, default), - RecBuf = get_opt(Opts, recbuf, default), - BindTo = get_opt(Opts, bind_to, false), - NoReuse = get_opt(Opts, no_reuse, false), - {ok, Port} = snmpm_config:system_info(port), - Domain = - case snmpm_config:system_info(domain) of - {ok, D} -> - D; - _ -> - snmpm_config:default_transport_domain() - end, - {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, Domain, BindTo, NoReuse), - %% Flow control -- FilterOpts = get_opt(Opts, filter, []), FilterMod = create_filter(FilterOpts), @@ -220,82 +214,197 @@ do_init(Server, NoteStore) -> {ok, ATL} = snmpm_config:system_info(audit_trail_log), Log = do_init_log(ATL), - %% -- Initiate counters --- - init_counters(), + {ok, DomainAddresses} = snmpm_config:system_info(transports), + ?vdebug("DomainAddresses: ~w",[DomainAddresses]), + CommonSocketOpts = common_socket_opts(Opts), + BindTo = get_opt(Opts, bind_to, false), + case + [begin + {IpPort, SocketOpts} = + socket_params(Domain, Address, BindTo, CommonSocketOpts), + Socket = socket_open(IpPort, SocketOpts), + #transport{socket = Socket, domain = Domain} + end || {Domain, Address} <- DomainAddresses] + of + [] -> + ?vinfo("No transports configured: ~p", [DomainAddresses]), + throw({error, {no_transports,DomainAddresses}}); + Transports -> + %% -- Initiate counters --- + init_counters(), + + %% -- We are done --- + State = #state{ + server = Server, + note_store = NoteStore, + mpd_state = MpdState, + transports = Transports, + log = Log, + irb = IRB, + irgc = IrGcRef, + filter = FilterMod}, + ?vdebug("started", []), + {ok, State} + end. - %% -- We are done --- - State = #state{server = Server, - note_store = NoteStore, - mpd_state = MpdState, - domain = Domain, - sock = Sock, - log = Log, - irb = IRB, - irgc = IrGcRef, - filter = FilterMod}, - ?vdebug("started", []), - {ok, State}. -%% Open port -do_open_port(Port, SendSz, RecvSz, Domain, BindTo, NoReuse) -> - ?vtrace("do_open_port -> entry with~n" - " Port: ~p~n" - " SendSz: ~p~n" - " RecvSz: ~p~n" - " Domain: ~p~n" - " BindTo: ~p~n" - " NoReuse: ~p", - [Port, SendSz, RecvSz, Domain, BindTo, NoReuse]), - IpOpts1 = bind_to(BindTo), - IpOpts2 = no_reuse(NoReuse), - IpOpts3 = recbuf(RecvSz), - IpOpts4 = sndbuf(SendSz), - IpOpts = - [binary, - snmp_conf:tdomain_to_family(Domain) | - IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], - OpenRes = - case init:get_argument(snmpm_fd) of - {ok, [[FdStr]]} -> - Fd = list_to_integer(FdStr), - gen_udp:open(0, [{fd, Fd}|IpOpts]); - error -> - gen_udp:open(Port, IpOpts) - end, - case OpenRes of + %% %% -- Socket -- + %% SndBuf = get_opt(Opts, sndbuf, default), + %% RecBuf = get_opt(Opts, recbuf, default), + %% BindTo = get_opt(Opts, bind_to, false), + %% NoReuse = get_opt(Opts, no_reuse, false), + + %% {ok, Port} = snmpm_config:system_info(port), + %% Domain = + %% case snmpm_config:system_info(domain) of + %% {ok, D} -> + %% D; + %% _ -> + %% snmpm_config:default_transport_domain() + %% end, + %% {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, Domain, BindTo, NoReuse), + + %% %% -- Initiate counters --- + %% init_counters(), + + %% %% -- We are done --- + %% State = #state{server = Server, + %% note_store = NoteStore, + %% mpd_state = MpdState, + %% domain = Domain, + %% sock = Sock, + %% log = Log, + %% irb = IRB, + %% irgc = IrGcRef, + %% filter = FilterMod}, + %% ?vdebug("started", []), + %% {ok, State}. + + +%% %% Open port +%% do_open_port(Port, SendSz, RecvSz, Domain, BindTo, NoReuse) -> +%% ?vtrace("do_open_port -> entry with~n" +%% " Port: ~p~n" +%% " SendSz: ~p~n" +%% " RecvSz: ~p~n" +%% " Domain: ~p~n" +%% " BindTo: ~p~n" +%% " NoReuse: ~p", +%% [Port, SendSz, RecvSz, Domain, BindTo, NoReuse]), +%% IpOpts1 = bind_to(BindTo), +%% IpOpts2 = no_reuse(NoReuse), +%% IpOpts3 = recbuf(RecvSz), +%% IpOpts4 = sndbuf(SendSz), +%% IpOpts = +%% [binary, +%% snmp_conf:tdomain_to_family(Domain) | +%% IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], +%% OpenRes = +%% case init:get_argument(snmpm_fd) of +%% {ok, [[FdStr]]} -> +%% Fd = list_to_integer(FdStr), +%% gen_udp:open(0, [{fd, Fd}|IpOpts]); +%% error -> +%% gen_udp:open(Port, IpOpts) +%% end, +%% case OpenRes of +%% {error, _} = Error -> +%% throw(Error); +%% OK -> +%% OK +%% end. + +socket_open(IpPort, SocketOpts) -> + ?vtrace("socket_open -> entry with~n" + " IpPort: ~p~n" + " SocketOpts: ~p", [IpPort, SocketOpts]), + case gen_udp:open(IpPort, SocketOpts) of {error, _} = Error -> throw(Error); - OK -> - OK + {ok, Socket} -> + Socket end. -bind_to(true) -> - case snmpm_config:system_info(address) of - {ok, Addr} when is_list(Addr) -> - [{ip, list_to_tuple(Addr)}]; - {ok, Addr} -> - [{ip, Addr}]; +%% bind_to(true) -> +%% case snmpm_config:system_info(address) of +%% {ok, Addr} when is_list(Addr) -> +%% [{ip, list_to_tuple(Addr)}]; +%% {ok, Addr} -> +%% [{ip, Addr}]; +%% _ -> +%% [] +%% end; +%% bind_to(_) -> +%% []. + +socket_params(Domain, {IpAddr, IpPort}, BindTo, CommonSocketOpts) -> + Family = snmp_conf:tdomain_to_family(Domain), + SocketOpts = + case Family of + inet6 -> + [Family, {ipv6_v6only, true} | CommonSocketOpts]; + Family -> + [Family | CommonSocketOpts] + end, + case Family of + inet -> + case init:get_argument(snmp_fd) of + {ok, [[FdStr]]} -> + Fd = list_to_integer(FdStr), + case BindTo of + true -> + {IpPort, [{ip, IpAddr}, {fd, Fd} | SocketOpts]}; + _ -> + {0, [{fd, Fd} | SocketOpts]} + end; + error -> + {IpPort, [{ip, IpAddr} | SocketOpts]} + end; _ -> - [] - end; -bind_to(_) -> - []. - -no_reuse(false) -> - [{reuseaddr, true}]; -no_reuse(_) -> - []. - -recbuf(default) -> - []; -recbuf(Sz) -> - [{recbuf, Sz}]. + case BindTo of + true -> + {IpPort, [{ip, IpAddr} | SocketOpts]}; + _ -> + {IpPort, SocketOpts} + end + end. -sndbuf(default) -> - []; -sndbuf(Sz) -> - [{sndbuf, Sz}]. +common_socket_opts(Opts) -> + [binary + | case get_opt(Opts, sndbuf, default) of + default -> + []; + Sz -> + [{sndbuf, Sz}] + end ++ + case get_opt(Opts, recbuf, default) of + default -> + []; + Sz -> + [{sndbuf, Sz}] + end ++ + case get_opt(Opts, no_reuse, false) of + false -> + [{reuseaddr, true}]; + _ -> + [] + end]. + +%% no_reuse(false) -> +%% [{reuseaddr, true}]; +%% no_reuse(_) -> +%% []. + +%% recbuf(default) -> +%% []; +%% recbuf(Sz) -> +%% [{recbuf, Sz}]. + +%% sndbuf(default) -> +%% []; +%% sndbuf(Sz) -> +%% [{sndbuf, Sz}]. create_filter(Opts) when is_list(Opts) -> @@ -439,11 +548,20 @@ handle_cast(Msg, State) -> %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_info( - {udp, Sock, Ip, Port, Bytes}, - #state{sock = Sock, domain = Domain} = State) -> - ?vlog("received ~w bytes from ~p:~p [~w]", [size(Bytes), Ip, Port, Sock]), - maybe_handle_recv_msg(Domain, {Ip, Port}, Bytes, State), - {noreply, State}; + {udp, Socket, IpAddr, IpPort, Bytes}, + #state{transports = Transports} = State) -> + Size = byte_size(Bytes), + case lists:keyfind(Socket, #transport.socket, Transports) of + #transport{socket = Socket, domain = Domain} -> + ?vlog("received ~w bytes from ~p:~p [~w]", + [Size, IpAddr, IpPort, Socket]), + maybe_handle_recv_msg(Domain, {IpAddr, IpPort}, Bytes, State), + {noreply, State}; + false -> + warning_msg("Received ~w bytes on unknown port: ~p from ~s", + [Size, Socket, format_address({IpAddr, IpPort})]), + {noreply, State} + end; handle_info(inform_response_gc, State) -> ?vlog("received inform_response_gc message", []), @@ -488,54 +606,6 @@ do_close_log(_) -> %% Returns: {ok, NewState} %%---------------------------------------------------------------------- -code_change({down, _Vsn}, OldState, downgrade_to_pre_4_14) -> - ?d("code_change(down, downgrade_to_pre_4_14) -> entry with" - "~n OldState: ~p", [OldState]), - #state{server = Server, - note_store = NoteStore, - sock = Sock, - mpd_state = MpdState, - log = {OldLog, Type}, - irb = IRB, - irgc = IRGC} = OldState, - NewLog = snmp_log:downgrade(OldLog), - State = - {state, Server, NoteStore, Sock, MpdState, {NewLog, Type}, IRB, IRGC}, - {ok, State}; - -code_change({down, _Vsn}, OldState, downgrade_to_pre_4_16) -> - ?d("code_change(down, downgrade_to_pre_4_16) -> entry with" - "~n OldState: ~p", [OldState]), - {OldLog, Type} = OldState#state.log, - NewLog = snmp_log:downgrade(OldLog), - State = OldState#state{log = {NewLog, Type}}, - {ok, State}; - -% upgrade -code_change(_Vsn, OldState, upgrade_from_pre_4_14) -> - ?d("code_change(up, upgrade_from_pre_4_14) -> entry with" - "~n OldState: ~p", [OldState]), - {state, Server, NoteStore, Sock, MpdState, {OldLog, Type}, IRB, IRGC} = - OldState, - NewLog = snmp_log:upgrade(OldLog), - State = #state{server = Server, - note_store = NoteStore, - sock = Sock, - mpd_state = MpdState, - log = {NewLog, Type}, - irb = IRB, - irgc = IRGC, - filter = ?DEFAULT_FILTER_MODULE}, - {ok, State}; - -code_change(_Vsn, OldState, upgrade_from_pre_4_16) -> - ?d("code_change(up, upgrade_from_pre_4_16) -> entry with" - "~n OldState: ~p", [OldState]), - {OldLog, Type} = OldState#state.log, - NewLog = snmp_log:upgrade(OldLog), - State = OldState#state{log = {NewLog, Type}}, - {ok, State}; - code_change(_Vsn, State, _Extra) -> ?d("code_change -> entry with" "~n Vsn: ~p" @@ -550,8 +620,8 @@ code_change(_Vsn, State, _Extra) -> maybe_handle_recv_msg( Domain, Addr, Bytes, - #state{filter = FilterMod, domain = ManagerDomain} = State) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{filter = FilterMod, transports = Transports} = State) -> + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_recv(Arg1, Arg2)) of false -> %% Drop the received packet @@ -569,10 +639,11 @@ handle_recv_msg(Domain, Addr, Bytes, #state{server = Pid}) handle_recv_msg( Domain, Addr, Bytes, - #state{server = Pid, - note_store = NoteStore, - mpd_state = MpdState, - log = Log} = State) -> + #state{ + server = Pid, + note_store = NoteStore, + mpd_state = MpdState, + log = Log} = State) -> Logger = logger(Log, read, Domain, Addr), case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, MpdState, NoteStore, Logger)) of @@ -603,8 +674,8 @@ handle_recv_msg( maybe_handle_recv_pdu( Domain, Addr, Vsn, #pdu{type = Type} = Pdu, PduMS, ACM, Logger, - #state{filter = FilterMod, domain = ManagerDomain} = State) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{filter = FilterMod, transports = Transports} = State) -> + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, Type)) of false -> inc(netIfPduInDrops), @@ -615,9 +686,9 @@ maybe_handle_recv_pdu( end; maybe_handle_recv_pdu( Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, - #state{filter = FilterMod, domain = ManagerDomain} = State) + #state{filter = FilterMod, transports = Transports} = State) when is_record(Trap, trappdu) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, trappdu)) of false -> inc(netIfPduInDrops), @@ -718,10 +789,11 @@ handle_inform_response(Ref, Domain, Addr, State) -> maybe_send_inform_response( RePdu, Vsn, ACM, Domain, Addr, Logger, - #state{server = Pid, - filter = FilterMod, - domain = ManagerDomain} = State) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{ + server = Pid, + filter = FilterMod, + transports = Transports} = State) -> + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_send_pdu( Arg1, Arg2, pdu_type_of(RePdu))) of @@ -774,8 +846,8 @@ irgc_stop(Ref) -> maybe_handle_send_pdu( Pdu, Vsn, MsgData, Domain, Addr, - #state{filter = FilterMod, domain = ManagerDomain} = State) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{filter = FilterMod, transports = Transports} = State) -> + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_send_pdu(Arg1, Arg2, pdu_type_of(Pdu))) of false -> inc(netIfPduOutDrops), @@ -786,9 +858,10 @@ maybe_handle_send_pdu( handle_send_pdu( Pdu, Vsn, MsgData, Domain, Addr, - #state{server = Pid, - note_store = NoteStore, - log = Log} = State) -> + #state{ + server = Pid, + note_store = NoteStore, + log = Log} = State) -> Logger = logger(Log, write, Domain, Addr), case (catch snmpm_mpd:generate_msg( Vsn, NoteStore, Pdu, MsgData, Logger)) of @@ -806,36 +879,52 @@ handle_send_pdu( maybe_udp_send( Domain, Addr, Msg, - #state{sock = Sock, filter = FilterMod, domain = ManagerDomain}) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{filter = FilterMod, transports = Transports}) -> + To = {Domain, Addr}, + {Arg1, Arg2} = fix_filter_address(Transports, To), case (catch FilterMod:accept_send(Arg1, Arg2)) of false -> inc(netIfMsgOutDrops), ok; _ -> - %% XXX There should be some kind of lookup of socket - %% from transport domain here - {Ip, Port} = Addr, - udp_send(Sock, Ip, Port, Msg) + case select_transport_from_domain(Domain, Transports) of + false -> + error_msg( + "Can not find transport~n" + " size: ~p~n" + " to: ~s", + [sz(Msg), format_address(To)]); + #transport{socket = Socket} -> + udp_send(Socket, Addr, Msg) + end end. - - -udp_send(Sock, Ip, Port, Msg) -> - case (catch gen_udp:send(Sock, Ip, Port, Msg)) of + +udp_send(Sock, To, Msg) -> + {IpAddr, IpPort} = + case To of + {Domain, Addr} when is_atom(Domain) -> + Addr; + {_, P} = Addr when is_integer(P) -> + Addr + end, + try gen_udp:send(Sock, IpAddr, IpPort, Msg) of ok -> ?vdebug("sent ~w bytes to ~w:~w [~w]", - [sz(Msg), Ip, Port, Sock]), + [sz(Msg), IpAddr, IpPort, Sock]), ok; {error, Reason} -> - error_msg("failed sending message to ~p:~p: " - "~n ~p",[Ip, Port, Reason]); - Error -> - error_msg("failed sending message to ~p:~p: " - "~n ~p",[Ip, Port, Error]) + error_msg("failed sending message to ~p:~p:~n" + " ~p",[IpAddr, IpPort, Reason]) + catch + error:Error -> + error_msg("failed sending message to ~p:~p:~n" + " error:~p~n" + " ~p", + [IpAddr, IpPort, Error, erlang:get_stacktrace()]) end. sz(B) when is_binary(B) -> - size(B); + byte_size(B); sz(L) when is_list(L) -> length(L); sz(_) -> @@ -1025,26 +1114,45 @@ handle_set_log_type(State, _NewType) -> {State, {error, not_enabled}}. +select_transport_from_domain(Domain, Transports) when is_atom(Domain) -> + Pos = #transport.domain, + case lists:keyfind(Domain, Pos, Transports) of + #transport{domain = Domain} = Transport -> + Transport; + false when Domain == snmpUDPDomain -> + lists:keyfind(transportDomainUdpIpv4, Pos, Transports); + false when Domain == transportDomainUdpIpv4 -> + lists:keyfind(snmpUDPDomain, Pos, Transports); + false -> + false + end. + %% If the manager uses legacy snmpUDPDomain e.g has not set %% {domain, _}, then make sure snmpm_network_interface_filter %% gets legacy arguments to not break backwards compatibility. %% -fix_filter_address(snmpUDPDomain, {Domain, Addr}) - when Domain =:= snmpUDPDomain; - Domain =:= transportDomainUdpIpv4 -> - Addr; -fix_filter_address(_ManagerDomain, {Domain, _} = Address) - when is_atom(Domain) -> - Address; -fix_filter_address(snmpUDPDomain, {_, Port} = Addr) - when is_integer(Port) -> - Addr. +fix_filter_address(Transports, Address) -> + DefaultDomain = snmpm_config:default_transport_domain(), + case Transports of + [#transport{domain = DefaultDomain}, DefaultDomain] -> + case Address of + {Domain, Addr} when is_atom(Domain) -> + Addr; + {_, IpPort} = Addr when is_integer(IpPort) -> + Addr + end; + _ -> + Address + end. address(Domain, Addr) when is_atom(Domain) -> {Domain, Addr}; address(Ip, Port) when is_integer(Port) -> {snmpm_config:default_transport_domain(), {Ip, Port}}. +format_address(Address) -> + iolist_to_binary(snmp_conf:mk_addr_string(Address)). + %% ------------------------------------------------------------------- make_response_pdu(#pdu{request_id = ReqId, varbinds = Vbs}) -> @@ -1130,10 +1238,11 @@ get_opt(Opts, Key, Def) -> %% ------------------------------------------------------------------- -get_info(#state{sock = Id}) -> +get_info(#state{transports = Transports}) -> ProcSize = proc_mem(self()), - PortInfo = get_port_info(Id), - [{process_memory, ProcSize}, {port_info, PortInfo}]. + [{process_memory, ProcSize} + | [{port_info, get_port_info(Socket)} + || #transport{socket = Socket} <- Transports]]. proc_mem(P) when is_pid(P) -> case (catch erlang:process_info(P, memory)) of @@ -1248,4 +1357,3 @@ call(Pid, Req, Timeout) -> cast(Pid, Msg) -> gen_server:cast(Pid, Msg). - diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl index 9e9865f3b5..0a50174adc 100644 --- a/lib/snmp/src/misc/snmp_config.erl +++ b/lib/snmp/src/misc/snmp_config.erl @@ -47,8 +47,8 @@ write_agent_snmp_vacm_conf/3, write_manager_snmp_files/8, - write_manager_snmp_conf/5, - write_manager_snmp_users_conf/2, + write_manager_snmp_conf/4, write_manager_snmp_conf/5, + write_manager_snmp_users_conf/2, write_manager_snmp_agents_conf/2, write_manager_snmp_usm_conf/2 @@ -2116,7 +2116,24 @@ write_manager_snmp_files(Dir, IP, Port, MMS, EngineID, %% ------ manager.conf ------ %% -write_manager_snmp_conf(Dir, IP, Port, MMS, EngineID) -> +write_manager_snmp_conf(Dir, Transports, MMS, EngineID) -> + Comment = +"%% This file defines the Manager local configuration info\n" +"%% Each row is a 2-tuple:\n" +"%% {Variable, Value}.\n" +"%% For example\n" +"%% {transports, [{transportDomainUdpIpv4, {{127,42,17,5}, 5000}}]}.\n" +"%% {engine_id, \"managerEngine\"}.\n" +"%% {max_message_size, 484}.\n" +"%%\n\n", + Hdr = header() ++ Comment, + Conf = + [{transports, Transports}, + {engine_id, EngineID}, + {max_message_size, MMS}], + write_manager_config(Dir, Hdr, Conf). + +write_manager_snmp_conf(Dir, Domain_or_IP, Addr_or_Port, MMS, EngineID) -> Comment = "%% This file defines the Manager local configuration info\n" "%% Each row is a 2-tuple:\n" @@ -2129,15 +2146,14 @@ write_manager_snmp_conf(Dir, IP, Port, MMS, EngineID) -> "%%\n\n", Hdr = header() ++ Comment, Conf = - case Port of - {Addr, P} when is_integer(P), is_atom(IP) -> - Domain = IP, - [{domain, Domain}, - {port, P}, - {address, Addr}]; - _ when is_integer(Port) -> - [{port, Port}, - {address, IP}] + case Addr_or_Port of + {IP, Port} when is_integer(Port), is_atom(Domain_or_IP) -> + [{domain, Domain_or_IP}, + {port, Port}, + {address, IP}]; + _ when is_integer(Addr_or_Port) -> + [{port, Addr_or_Port}, + {address, Domain_or_IP}] end ++ [{engine_id, EngineID}, {max_message_size, MMS}], -- cgit v1.2.3 From 39176f2ab7f07c676e797455000bc2dfc6bb751c Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Fri, 15 Aug 2014 15:10:33 +0200 Subject: Write manager IPv4+IPv6 test --- lib/snmp/test/snmp_manager_user.erl | 15 +- lib/snmp/test/snmp_to_snmpnet_SUITE.erl | 154 +++++++++++++++++---- .../test/snmp_to_snmpnet_SUITE_data/snmpd.conf | 12 ++ 3 files changed, 155 insertions(+), 26 deletions(-) create mode 100644 lib/snmp/test/snmp_to_snmpnet_SUITE_data/snmpd.conf diff --git a/lib/snmp/test/snmp_manager_user.erl b/lib/snmp/test/snmp_manager_user.erl index ddbe156130..46c2b316be 100644 --- a/lib/snmp/test/snmp_manager_user.erl +++ b/lib/snmp/test/snmp_manager_user.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% Copyright Ericsson AB 2005-2014. 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 @@ -109,7 +109,18 @@ start_link(Parent, Id) -> proc_lib:start_link(?MODULE, main, [true, Parent, self(), Id]). stop() -> - cast(stop). + MRef = erlang:monitor(process, ?SERVER), + cast(stop), + receive {'DOWN', MRef, _, _, Info} -> + case Info of + noproc -> + ok; + noconnection -> + ok; + normal -> + ok + end + end. info() -> call(info). diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl index 6e9c57bce9..1c2e08dc41 100644 --- a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl @@ -19,6 +19,7 @@ %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test suite uses the following external programs: %% snmpget From packet 'snmp' (in Ubuntu 12.04) +%% snmpd From packet 'snmpd' (in Ubuntu 12.04) %% snmptrapd From packet 'snmpd' (in Ubuntu 12.04) %% They originate from the Net-SNMP applications, see: %% http://net-snmp.sourceforge.net/ @@ -33,6 +34,7 @@ -include_lib("snmp/include/STANDARD-MIB.hrl"). -define(AGENT_ENGINE_ID, "ErlangSnmpAgent"). +-define(MANAGER_ENGINE_ID, "ErlangSnmpManager"). -define(AGENT_PORT, 4000). -define(MANAGER_PORT, 8989). -define(DEFAULT_MAX_MESSAGE_SIZE, 484). @@ -56,22 +58,27 @@ all() -> groups() -> [{ipv4, [], - [{group, get}, - {group, inform} + [{group, snmpget}, + {group, snmptrapd}, + {group, snmpd} ]}, {ipv6, [], - [{group, get}, - {group, inform} + [{group, snmpget}, + {group, snmptrapd}, + {group, snmpd} ]}, {ipv4_ipv6, [], - [{group, get}, - {group, inform} + [{group, snmpget}, + {group, snmptrapd}, + {group, snmpd} ]}, %% - {get, [], + {snmpget, [], [erlang_agent_netsnmp_get]}, - {inform, [], - [erlang_agent_netsnmp_inform]} + {snmptrapd, [], + [erlang_agent_netsnmp_inform]}, + {snmpd, [], + [erlang_manager_netsnmp_get]} ]. init_per_suite(Config) -> @@ -87,12 +94,15 @@ init_per_group(ipv6, Config) -> init_per_group(ipv4_ipv6, Config) -> init_per_group_ipv6([inet, inet6], Config); %% -init_per_group(get, Config) -> +init_per_group(snmpget = Exec, Config) -> %% From Ubuntu package snmp - find_executable(snmpget, Config); -init_per_group(inform, Config) -> + init_per_group_agent(Exec, Config); +init_per_group(snmptrapd = Exec, Config) -> %% From Ubuntu package snmpd - find_executable(snmptrapd, Config); + init_per_group_agent(Exec, Config); +init_per_group(snmpd = Exec, Config) -> + %% From Ubuntu package snmp + init_per_group_manager(Exec, Config); %% init_per_group(_, Config) -> Config. @@ -106,10 +116,8 @@ init_per_group_ipv6(Families, Config) -> end. init_per_group_ip(Families, Config) -> - Dir = ?config(priv_dir, Config), AgentPort = ?config(agent_port, Config), ManagerPort = ?config(manager_port, Config), - Versions = [v2], {ok, Host} = inet:gethostname(), Transports = [begin @@ -121,10 +129,22 @@ init_per_group_ip(Families, Config) -> {ok, Addr} = inet:getaddr(Host, Family), {domain(Family), {Addr, ManagerPort}} end || Family <- Families], + [{transports, Transports}, {targets, Targets} | Config]. + +init_per_group_agent(Exec, Config) -> + Versions = [v2], + Dir = ?config(priv_dir, Config), + Transports = ?config(transports, Config), + Targets = ?config(targets, Config), agent_config(Dir, Transports, Targets, Versions), - [{port, ?AGENT_PORT}, {snmp_versions, Versions}, - {transports, Transports}, {targets, Targets} - | Config]. + find_executable(Exec, [{snmp_versions, Versions} | Config]). + +init_per_group_manager(Exec, Config) -> + Versions = [v2], + Dir = ?config(priv_dir, Config), + Targets = ?config(targets, Config), + manager_config(Dir, Targets), + find_executable(Exec, [{snmp_versions, Versions} | Config]). @@ -179,7 +199,12 @@ find_sys_executable(Exec, ExecStr, [Dir | Dirs], Config) -> start_agent(Config) -> ok = application:load(snmp), - ok = application:set_env(snmp, agent, app_env(Config)), + ok = application:set_env(snmp, agent, agent_app_env(Config)), + ok = application:start(snmp). + +start_manager(Config) -> + ok = application:load(snmp), + ok = application:set_env(snmp, manager, manager_app_env(Config)), ok = application:start(snmp). %%-------------------------------------------------------------------- @@ -198,6 +223,39 @@ erlang_agent_netsnmp_get(Config) when is_list(Config) -> || Transport <- Transports], ok. +%%-------------------------------------------------------------------- +erlang_manager_netsnmp_get() -> + [{doc,"Test that the erlang snmp manager can access snmpnet agent"}]. + +erlang_manager_netsnmp_get(Config) when is_list(Config) -> + Community = "happy-testing", + SysDescr = "Net-SNMP agent", + TargetName = "Target Net-SNMP agent", + Transports = ?config(transports, Config), + ProgHandle = start_snmpd(Community, SysDescr, Config), + start_manager(Config), + snmp_manager_user:start_link(self(), test_user), + [snmp_manager_user:register_agent( + TargetName++domain_suffix(Domain), + [{reg_type, target_name}, + {tdomain, Domain}, {taddress, Addr}, + {community, Community}, {engine_id, "EngineId"}, + {version, v2}, {sec_model, v2c}, {sec_level, noAuthNoPriv}]) + || {Domain, Addr} <- Transports], + Results = + [snmp_manager_user:sync_get( + TargetName++domain_suffix(Domain), + [?sysDescr_instance]) + || {Domain, _} <- Transports], + ct:pal("sync_get -> ~p", [Results]), + snmp_manager_user:stop(), + stop_program(ProgHandle), + [{ok, + {noError, 0, + [{varbind, ?sysDescr_instance, 'OCTET STRING', SysDescr,1}] }, + _} = R || R <- Results], + ok. + %%-------------------------------------------------------------------- erlang_agent_netsnmp_inform(Config) when is_list(Config) -> DataDir = ?config(data_dir, Config), @@ -267,7 +325,29 @@ start_snmptrapd(Mibs, Config) -> {ok, StartCheckMP} = re:compile("NET-SNMP version ", [anchored]), start_program(snmptrapd, SnmptrapdArgs, StartCheckMP, Config). +start_snmpd(Community, SysDescr, Config) -> + DataDir = ?config(data_dir, Config), + Targets = ?config(targets, Config), + Transports = ?config(transports, Config), + Port = mk_port_number(), + CommunityArgs = + ["--rocommunity"++domain_suffix(Domain)++"=" + ++Community++" "++inet_parse:ntoa(Ip) + || {Domain, {Ip, _}} <- Targets], + SnmpdArgs = + ["-f", "-r", %"-Dverbose", + "-c", filename:join(DataDir, "snmpd.conf"), + "-C", "-Lo", + "-m", "", + "--sysDescr="++SysDescr, + "--agentXSocket=tcp:localhost:"++integer_to_list(Port)] + ++ CommunityArgs + ++ [net_snmp_addr_str(Transports)], + {ok, StartCheckMP} = re:compile("NET-SNMP version ", [anchored]), + start_program(snmpd, SnmpdArgs, StartCheckMP, Config). + start_program(Prog, Args, StartCheckMP, Config) -> + ct:pal("Starting program: ~w ~p", [Prog, Args]), Path = ?config(Prog, Config), DataDir = ?config(data_dir, Config), StartWrapper = filename:join(DataDir, "start_stop_wrapper"), @@ -318,12 +398,13 @@ wait_program_stop({Pid, Mon}) -> end. run_program(Parent, StartWrapper, ProgAndArgs) -> + [Prog | _] = ProgAndArgs, Port = open_port( {spawn_executable, StartWrapper}, [{args, ProgAndArgs}, binary, stderr_to_stdout, {line, 80}, exit_status]), - ct:pal("Prog ~p started: ~p", [Port, ProgAndArgs]), + ct:pal("Prog ~p started: ~p", [Port, Prog]), run_program_loop(Parent, Port, []). run_program_loop(Parent, Port, Buf) -> @@ -352,7 +433,7 @@ run_program_loop(Parent, Port, Buf) -> end. -app_env(Config) -> +agent_app_env(Config) -> Dir = ?config(priv_dir, Config), Vsns = ?config(snmp_versions, Config), [{versions, Vsns}, @@ -372,6 +453,18 @@ app_env(Config) -> {note_store, [{verbosity, silence}]}, {net_if, [{verbosity, trace}]}]. +manager_app_env(Config) -> + Dir = ?config(priv_dir, Config), + Vsns = ?config(snmp_versions, Config), + [{versions, Vsns}, + {audit_trail_log, [{type, read_write}, + {dir, Dir}, + {size, {10240, 10}}]}, + {config, [{dir, Dir}, + {db_dir, Dir}, + {verbosity, trace}]} + ]. + oid_str([1 | Ints]) -> "iso." ++ oid_str_tl(Ints); oid_str(Ints) -> @@ -384,9 +477,6 @@ oid_str_tl([Int]) -> oid_str_tl([Int | Ints]) -> integer_to_list(Int) ++ "." ++ oid_str_tl(Ints). -agent_config(Dir, Transports, TargetDomain, TargetAddr, Versions) -> - agent_config(Dir, Transports, [{TargetDomain, TargetAddr}], Versions). -%% agent_config(Dir, Transports, Targets, Versions) -> EngineID = ?AGENT_ENGINE_ID, MMS = ?DEFAULT_MAX_MESSAGE_SIZE, @@ -403,6 +493,11 @@ agent_config(Dir, Transports, Targets, Versions) -> ok = snmp_config:write_agent_snmp_notify_conf(Dir, inform), ok = snmp_config:write_agent_snmp_vacm_conf(Dir, Versions, none). +manager_config(Dir, Targets) -> + EngineID = ?MANAGER_ENGINE_ID, + MMS = ?DEFAULT_MAX_MESSAGE_SIZE, + ok = snmp_config:write_manager_snmp_conf(Dir, Targets, MMS, EngineID). + net_snmp_version([v3 | _]) -> "-v3"; net_snmp_version([v2 | _]) -> @@ -431,3 +526,14 @@ net_snmp_addr_str({transportDomainUdpIpv6, {Addr, Port}}) -> "udp6:[" ++ inet_parse:ntoa(Addr) ++ "]:" ++ integer_to_list(Port). + +domain_suffix(transportDomainUdpIpv4) -> + ""; +domain_suffix(transportDomainUdpIpv6) -> + "6". + +mk_port_number() -> + {ok, Socket} = gen_udp:open(0, [{reuseaddr, true}]), + {ok, PortNum} = inet:port(Socket), + ok = gen_udp:close(Socket), + PortNum. diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE_data/snmpd.conf b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/snmpd.conf new file mode 100644 index 0000000000..2a5f31680f --- /dev/null +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE_data/snmpd.conf @@ -0,0 +1,12 @@ +sysLocation On the lab network +sysContact otptest + +createUser myinternaluser SHA dropdead + +agentSecName myinternaluser + +master agentx + +[snmp] +noPersistentLoad yes +noPersistentSave yes -- cgit v1.2.3 From e1a6e43da5b249dd75e2baadd494921cf1684323 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Mon, 18 Aug 2014 15:17:45 +0200 Subject: Improve testcase test for IPv6 capable host --- lib/snmp/.gitignore | 3 +-- lib/snmp/test/snmp_agent_test.erl | 17 ++++++++++++----- lib/snmp/test/snmp_manager_test.erl | 23 ++++++++++++++++++----- lib/snmp/test/snmp_to_snmpnet_SUITE.erl | 10 ++++++++-- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/lib/snmp/.gitignore b/lib/snmp/.gitignore index 650c1d6865..aef73491a4 100644 --- a/lib/snmp/.gitignore +++ b/lib/snmp/.gitignore @@ -5,5 +5,4 @@ *.rej doc/index.html - - +mibs/.index diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl index 9a9258aa91..05c91c37a3 100644 --- a/lib/snmp/test/snmp_agent_test.erl +++ b/lib/snmp/test/snmp_agent_test.erl @@ -651,11 +651,18 @@ init_per_group(GroupName, Config) -> init_per_group_ipv6(GroupName, Config, Init) -> case ct:require(ipv6_hosts) of ok -> - Init( - snmp_test_lib:init_group_top_dir( - GroupName, - [{ipfamily, inet6}, - {ip, ?LOCALHOST(inet6)} | lists:keydelete(ip, 1, Config)])); + case gen_udp:open(0, [inet6]) of + {ok, S} -> + ok = gen_udp:close(S), + Init( + snmp_test_lib:init_group_top_dir( + GroupName, + [{ipfamily, inet6}, + {ip, ?LOCALHOST(inet6)} + | lists:keydelete(ip, 1, Config)])); + {error, _} -> + {skip, "Host seems to not support IPv6"} + end; _ -> {skip, "Host does not support IPV6"} end. diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl index 78352e59cf..fa90872172 100644 --- a/lib/snmp/test/snmp_manager_test.erl +++ b/lib/snmp/test/snmp_manager_test.erl @@ -584,17 +584,30 @@ init_per_group(event_tests_mt = GroupName, Config) -> init_per_group(ipv6_mt = GroupName, Config) -> case ct:require(ipv6_hosts) of ok -> - ipv6_init( - snmp_test_lib:init_group_top_dir( - GroupName, - [{manager_net_if_module, snmpm_net_if_mt} | Config])); + case gen_udp:open(0, [inet6]) of + {ok, S} -> + ok = gen_udp:close(S), + ipv6_init( + snmp_test_lib:init_group_top_dir( + GroupName, + [{manager_net_if_module, snmpm_net_if_mt} + | Config])); + {error, _} -> + {skip, "Host seems to not support IPv6"} + end; _ -> {skip, "Host does not support IPV6"} end; init_per_group(ipv6 = GroupName, Config) -> case ct:require(ipv6_hosts) of ok -> - ipv6_init(snmp_test_lib:init_group_top_dir(GroupName, Config)); + case gen_udp:open(0, [inet6]) of + {ok, S} -> + ok = gen_udp:close(S), + ipv6_init(snmp_test_lib:init_group_top_dir(GroupName, Config)); + {error, _} -> + {skip, "Host seems to not support IPv6"} + end; _ -> {skip, "Host does not support IPV6"} end; diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl index 1c2e08dc41..5ce9cf9e5c 100644 --- a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl @@ -110,9 +110,15 @@ init_per_group(_, Config) -> init_per_group_ipv6(Families, Config) -> case ct:require(ipv6_hosts) of ok -> - init_per_group_ip(Families, Config); + case gen_udp:open(0, [inet6]) of + {ok, S} -> + ok = gen_udp:close(S), + init_per_group_ip(Families, Config); + {error, _} -> + {skip, "Host seems to not support IPv6"} + end; _ -> - {skip, "Host does not support IPV6"} + {skip, "Test config ipv6_hosts is missing"} end. init_per_group_ip(Families, Config) -> -- cgit v1.2.3 From 0685f5c84f0f6ecfd8535d471d082271e77517c6 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 19 Aug 2014 10:22:46 +0200 Subject: Avoid test case known to fail --- lib/snmp/test/snmp_agent_test.erl | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl index 05c91c37a3..b4770ad0a9 100644 --- a/lib/snmp/test/snmp_agent_test.erl +++ b/lib/snmp/test/snmp_agent_test.erl @@ -532,6 +532,7 @@ groups() -> {v3_inform, [], v3_inform_cases()}, {v3_security, [], v3_security_cases()}, {standard_mibs, [], standard_mibs_cases()}, + {standard_mibs_ipv6, [], standard_mibs_cases_ipv6()}, {standard_mibs_2, [], standard_mibs2_cases()}, {standard_mibs_3, [], standard_mibs3_cases()}, {reported_bugs, [], reported_bugs_cases()}, @@ -1721,7 +1722,7 @@ v1_cases_ipv6() -> next_across_sa, undo, %% {group, reported_bugs}, - {group, standard_mibs}, % snmp_standard_mib still failing, sends v1 trap + {group, standard_mibs_ipv6}, sparse_table, %% cnt_64, % sends v1 trap opaque @@ -4843,6 +4844,15 @@ standard_mibs_cases() -> snmp_view_based_acm_mib ]. +standard_mibs_cases_ipv6() -> + [ + %% snmp_standard_mib, % Sending v1 traps does not work over IPv6 + snmp_community_mib, + snmp_framework_mib, + snmp_target_mib, + snmp_notification_mib, + snmp_view_based_acm_mib + ]. %%----------------------------------------------------------------- %% For this test, the agent is configured for v1. -- cgit v1.2.3 From c49a434098b715b5d7d47ebcb1c2b9a22d0ee500 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 19 Aug 2014 15:42:49 +0200 Subject: Implement IPv4+IPv6 in MT manager --- lib/snmp/src/manager/snmpm_net_if_mt.erl | 799 ++++++++++++++++++++----------- lib/snmp/test/snmp_to_snmpnet_SUITE.erl | 16 +- 2 files changed, 535 insertions(+), 280 deletions(-) diff --git a/lib/snmp/src/manager/snmpm_net_if_mt.erl b/lib/snmp/src/manager/snmpm_net_if_mt.erl index 2937f5cc87..516a2f444a 100644 --- a/lib/snmp/src/manager/snmpm_net_if_mt.erl +++ b/lib/snmp/src/manager/snmpm_net_if_mt.erl @@ -59,8 +59,9 @@ { server, note_store, - domain, - sock, +%% domain, +%% sock, + transports = [], mpd_state, log, irb = auto, % auto | {user, integer()} @@ -68,6 +69,9 @@ filter }). +-record(transport, + {socket, + domain = snmpUDPDomain}). -define(DEFAULT_FILTER_MODULE, snmpm_net_if_filter). -define(DEFAULT_FILTER_OPTS, [{module, ?DEFAULT_FILTER_MODULE}]). @@ -107,12 +111,12 @@ send_pdu(Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port) -> send_pdu(Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port, ExtraInfo) when is_record(Pdu, pdu) -> ?d("send_pdu -> entry with~n" - " Pid: ~p~n" - " Pdu: ~p~n" - " Vsn: ~p~n" - " MsgData: ~p~n" - " Domain/IP: ~p~n" - " Addr/Port : ~p", + " Pid: ~p~n" + " Pdu: ~p~n" + " Vsn: ~p~n" + " MsgData: ~p~n" + " Domain/IP: ~p~n" + " Addr/Port: ~p", [Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port]), {Domain, Addr} = address(Domain_or_Ip, Addr_or_Port), cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo}). @@ -161,12 +165,17 @@ init([Server, NoteStore]) -> ?d("init -> entry with" "~n Server: ~p" "~n NoteStore: ~p", [Server, NoteStore]), - case (catch do_init(Server, NoteStore)) of + try do_init(Server, NoteStore) + catch {error, Reason} -> - {stop, Reason}; - {ok, State} -> - {ok, State} + {stop, Reason} end. + %% case (catch do_init(Server, NoteStore)) of + %% {error, Reason} -> + %% {stop, Reason}; + %% {ok, State} -> + %% {ok, State} + %% end. do_init(Server, NoteStore) -> process_flag(trap_exit, true), @@ -199,21 +208,6 @@ do_init(Server, NoteStore) -> {ok, IRB} = snmpm_config:system_info(net_if_irb), IrGcRef = irgc_start(IRB), - %% -- Socket -- - SndBuf = get_opt(Opts, sndbuf, default), - RecBuf = get_opt(Opts, recbuf, default), - BindTo = get_opt(Opts, bind_to, false), - NoReuse = get_opt(Opts, no_reuse, false), - {ok, Port} = snmpm_config:system_info(port), - Domain = - case snmpm_config:system_info(domain) of - {ok, D} -> - D; - _ -> - snmpm_config:default_transport_domain() - end, - {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, Domain, BindTo, NoReuse), - %% Flow control -- FilterOpts = get_opt(Opts, filter, []), FilterMod = create_filter(FilterOpts), @@ -224,82 +218,197 @@ do_init(Server, NoteStore) -> Log = do_init_log(ATL), ?vdebug("Log: ~w", [Log]), - %% -- Initiate counters --- - init_counters(), - - %% -- We are done --- - State = #state{server = Server, - note_store = NoteStore, - mpd_state = MpdState, - domain = Domain, - sock = Sock, - log = Log, - irb = IRB, - irgc = IrGcRef, - filter = FilterMod}, - ?vdebug("started", []), - {ok, State}. + {ok, DomainAddresses} = snmpm_config:system_info(transports), + ?vdebug("DomainAddresses: ~w",[DomainAddresses]), + CommonSocketOpts = common_socket_opts(Opts), + BindTo = get_opt(Opts, bind_to, false), + case + [begin + {IpPort, SocketOpts} = + socket_params(Domain, Address, BindTo, CommonSocketOpts), + Socket = socket_open(IpPort, SocketOpts), + #transport{socket = Socket, domain = Domain} + end || {Domain, Address} <- DomainAddresses] + of + [] -> + ?vinfo("No transports configured: ~p", [DomainAddresses]), + throw({error, {no_transports,DomainAddresses}}); + Transports -> + %% -- Initiate counters --- + init_counters(), + + %% -- We are done --- + State = #state{ + server = Server, + note_store = NoteStore, + mpd_state = MpdState, + transports = Transports, + log = Log, + irb = IRB, + irgc = IrGcRef, + filter = FilterMod}, + ?vdebug("started", []), + {ok, State} + end. -%% Open port -do_open_port(Port, SendSz, RecvSz, Domain, BindTo, NoReuse) -> - ?vtrace("do_open_port -> entry with~n" - " Port: ~p~n" - " SendSz: ~p~n" - " RecvSz: ~p~n" - " Domain: ~p~n" - " BindTo: ~p~n" - " NoReuse: ~p", - [Port, SendSz, RecvSz, Domain, BindTo, NoReuse]), - IpOpts1 = bind_to(BindTo), - IpOpts2 = no_reuse(NoReuse), - IpOpts3 = recbuf(RecvSz), - IpOpts4 = sndbuf(SendSz), - IpOpts = - [binary, - snmp_conf:tdomain_to_family(Domain) | - IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], - OpenRes = - case init:get_argument(snmpm_fd) of - {ok, [[FdStr]]} -> - Fd = list_to_integer(FdStr), - gen_udp:open(0, [{fd, Fd}|IpOpts]); - error -> - gen_udp:open(Port, IpOpts) - end, - case OpenRes of + + %% %% -- Socket -- + %% SndBuf = get_opt(Opts, sndbuf, default), + %% RecBuf = get_opt(Opts, recbuf, default), + %% BindTo = get_opt(Opts, bind_to, false), + %% NoReuse = get_opt(Opts, no_reuse, false), + + %% {ok, Port} = snmpm_config:system_info(port), + %% Domain = + %% case snmpm_config:system_info(domain) of + %% {ok, D} -> + %% D; + %% _ -> + %% snmpm_config:default_transport_domain() + %% end, + %% {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, Domain, BindTo, NoReuse), + + %% %% -- Initiate counters --- + %% init_counters(), + + %% %% -- We are done --- + %% State = #state{server = Server, + %% note_store = NoteStore, + %% mpd_state = MpdState, + %% domain = Domain, + %% sock = Sock, + %% log = Log, + %% irb = IRB, + %% irgc = IrGcRef, + %% filter = FilterMod}, + %% ?vdebug("started", []), + %% {ok, State}. + + +%% %% Open port +%% do_open_port(Port, SendSz, RecvSz, Domain, BindTo, NoReuse) -> +%% ?vtrace("do_open_port -> entry with~n" +%% " Port: ~p~n" +%% " SendSz: ~p~n" +%% " RecvSz: ~p~n" +%% " Domain: ~p~n" +%% " BindTo: ~p~n" +%% " NoReuse: ~p", +%% [Port, SendSz, RecvSz, Domain, BindTo, NoReuse]), +%% IpOpts1 = bind_to(BindTo), +%% IpOpts2 = no_reuse(NoReuse), +%% IpOpts3 = recbuf(RecvSz), +%% IpOpts4 = sndbuf(SendSz), +%% IpOpts = +%% [binary, +%% snmp_conf:tdomain_to_family(Domain) | +%% IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], +%% OpenRes = +%% case init:get_argument(snmpm_fd) of +%% {ok, [[FdStr]]} -> +%% Fd = list_to_integer(FdStr), +%% gen_udp:open(0, [{fd, Fd}|IpOpts]); +%% error -> +%% gen_udp:open(Port, IpOpts) +%% end, +%% case OpenRes of +%% {error, _} = Error -> +%% throw(Error); +%% OK -> +%% OK +%% end. + +socket_open(IpPort, SocketOpts) -> + ?vtrace("socket_open -> entry with~n" + " IpPort: ~p~n" + " SocketOpts: ~p", [IpPort, SocketOpts]), + case gen_udp:open(IpPort, SocketOpts) of {error, _} = Error -> throw(Error); - OK -> - OK + {ok, Socket} -> + Socket end. -bind_to(true) -> - case snmpm_config:system_info(address) of - {ok, Addr} when is_list(Addr) -> - [{ip, list_to_tuple(Addr)}]; - {ok, Addr} -> - [{ip, Addr}]; +%% bind_to(true) -> +%% case snmpm_config:system_info(address) of +%% {ok, Addr} when is_list(Addr) -> +%% [{ip, list_to_tuple(Addr)}]; +%% {ok, Addr} -> +%% [{ip, Addr}]; +%% _ -> +%% [] +%% end; +%% bind_to(_) -> +%% []. + +socket_params(Domain, {IpAddr, IpPort}, BindTo, CommonSocketOpts) -> + Family = snmp_conf:tdomain_to_family(Domain), + SocketOpts = + case Family of + inet6 -> + [Family, {ipv6_v6only, true} | CommonSocketOpts]; + Family -> + [Family | CommonSocketOpts] + end, + case Family of + inet -> + case init:get_argument(snmp_fd) of + {ok, [[FdStr]]} -> + Fd = list_to_integer(FdStr), + case BindTo of + true -> + {IpPort, [{ip, IpAddr}, {fd, Fd} | SocketOpts]}; + _ -> + {0, [{fd, Fd} | SocketOpts]} + end; + error -> + {IpPort, [{ip, IpAddr} | SocketOpts]} + end; _ -> - [] - end; -bind_to(_) -> - []. - -no_reuse(false) -> - [{reuseaddr, true}]; -no_reuse(_) -> - []. - -recbuf(default) -> - []; -recbuf(Sz) -> - [{recbuf, Sz}]. + case BindTo of + true -> + {IpPort, [{ip, IpAddr} | SocketOpts]}; + _ -> + {IpPort, SocketOpts} + end + end. -sndbuf(default) -> - []; -sndbuf(Sz) -> - [{sndbuf, Sz}]. +common_socket_opts(Opts) -> + [binary + | case get_opt(Opts, sndbuf, default) of + default -> + []; + Sz -> + [{sndbuf, Sz}] + end ++ + case get_opt(Opts, recbuf, default) of + default -> + []; + Sz -> + [{sndbuf, Sz}] + end ++ + case get_opt(Opts, no_reuse, false) of + false -> + [{reuseaddr, true}]; + _ -> + [] + end]. + +%% no_reuse(false) -> +%% [{reuseaddr, true}]; +%% no_reuse(_) -> +%% []. + +%% recbuf(default) -> +%% []; +%% recbuf(Sz) -> +%% [{recbuf, Sz}]. + +%% sndbuf(default) -> +%% []; +%% sndbuf(Sz) -> +%% [{sndbuf, Sz}]. create_filter(Opts) when is_list(Opts) -> @@ -338,7 +447,8 @@ do_init_log(true) -> Function = increment_counter, Args = [atl_seqno, Initial, Max], SeqNoGen = {Module, Function, Args}, - case snmp_log:create(Name, File, SeqNoGen, Size, Repair, true) of + case snmp_log:create( + Name, File, SeqNoGen, Size, Repair, true) of {ok, Log} -> ?vdebug("log created: ~w", [Log]), {Name, Log, Type}; @@ -356,8 +466,6 @@ do_init_log(true) -> end. -%% ---------------------------------------------------------------------- - %%-------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | @@ -449,11 +557,20 @@ handle_cast(Msg, State) -> %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_info( - {udp, Sock, Ip, Port, Bytes}, - #state{sock = Sock, domain = Domain} = State) -> - ?vlog("received ~w bytes from ~p:~p", [size(Bytes), Ip, Port]), - handle_udp(Domain, {Ip, Port}, Bytes, State), - {noreply, State}; + {udp, Socket, IpAddr, IpPort, Bytes}, + #state{transports = Transports} = State) -> + Size = byte_size(Bytes), + case lists:keyfind(Socket, #transport.socket, Transports) of + #transport{socket = Socket, domain = Domain} -> + ?vlog("received ~w bytes from ~p:~p [~w]", + [Size, IpAddr, IpPort, Socket]), + handle_udp(Domain, {IpAddr, IpPort}, Bytes, State), + {noreply, State}; + false -> + warning_msg("Received ~w bytes on unknown port: ~p from ~s", + [Size, Socket, format_address({IpAddr, IpPort})]), + {noreply, State} + end; handle_info(inform_response_gc, State) -> ?vlog("received inform_response_gc message", []), @@ -466,11 +583,18 @@ handle_info({disk_log, _Node, Log, Info}, State) -> State2 = handle_disk_log(Log, Info, State), {noreply, State2}; -handle_info({'DOWN', _MRef, process, Pid, {net_if_worker, ExitStatus}}, +handle_info({'DOWN', _MRef, process, _Pid, {net_if_worker, _Result}}, State) -> - ?vdebug("received DOWN message from net_if-worker: " - "~n ExitStatus: ~p", [ExitStatus]), - handle_worker_exit(Pid, ExitStatus), + ?vdebug("received DOWN message from net_if worker [~w]: " + "~n Result: ~p", [_Pid, _Result]), + {noreply, State}; +handle_info( + {'DOWN', _MRef, process, Pid, + {net_if_worker, Failer, Class, Reason, Stacktrace} = _ExitStatus}, + State) -> + ?vdebug("received DOWN message from net_if worker [~w]: " + "~n ExitStatus: ~p", [Pid, _ExitStatus]), + Failer(Pid, Class, Reason, Stacktrace), {noreply, State}; handle_info(Info, State) -> @@ -512,99 +636,108 @@ code_change(_Vsn, State, _Extra) -> "~n Extra: ~p", [_Vsn, State, _Extra]), {ok, State}. - + %%%------------------------------------------------------------------- %%% Internal functions %%%------------------------------------------------------------------- handle_udp(Domain, Addr, Bytes, State) -> - Verbosity = get(verbosity), - spawn_opt( - fun() -> - Log = worker_init(State, Verbosity), - Res = - (catch maybe_handle_recv_msg( - Domain, Addr, Bytes, - State#state{log = Log})), - worker_exit(udp, {Domain, Addr}, Res) + worker( + fun (S) -> + maybe_handle_recv_msg(Domain, Addr, Bytes, S) end, - [monitor]). + fun (Pid, Class, Reason, Stacktrace) -> + warning_msg( + "Worker process (~p) terminated " + "while processing (incomming) message from %s:~n" + "~w:~w at ~p", + [Pid, snmp_conf:mk_addr_string({Domain, Addr}), + Class, Reason, Stacktrace]) + end, + State). + + %% Verbosity = get(verbosity), + %% spawn_opt( + %% fun() -> + %% Log = worker_init(State, Verbosity), + %% Res = + %% (catch maybe_handle_recv_msg( + %% Domain, Addr, Bytes, + %% State#state{log = Log})), + %% worker_exit(udp, {Domain, Addr}, Res) + %% end, + %% [monitor]). maybe_handle_recv_msg( Domain, Addr, Bytes, - #state{filter = FilterMod, domain = ManagerDomain} = State) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{filter = FilterMod, transports = Transports} = State) -> + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_recv(Arg1, Arg2)) of false -> %% Drop the received packet - inc(netIfMsgInDrops), - ok; + inc(netIfMsgInDrops); _ -> handle_recv_msg(Domain, Addr, Bytes, State) - end. + end, + ok. handle_recv_msg(Domain, Addr, Bytes, #state{server = Pid}) when is_binary(Bytes) andalso (size(Bytes) =:= 0) -> - Pid ! {snmp_error, {empty_message, Domain, Addr}, Domain, Addr}, - ok; - + Pid ! {snmp_error, {empty_message, Domain, Addr}, Domain, Addr}; +%% handle_recv_msg( Domain, Addr, Bytes, - #state{server = Pid, - note_store = NoteStore, - mpd_state = MpdState, - log = Log} = State) -> + #state{ + server = Pid, + note_store = NoteStore, + mpd_state = MpdState, + log = Log} = State) -> Logger = logger(Log, read, Domain, Addr), - case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, - MpdState, NoteStore, Logger)) of + case (catch snmpm_mpd:process_msg( + Bytes, Domain, Addr, MpdState, NoteStore, Logger)) of {ok, Vsn, Pdu, MS, ACM} -> - maybe_handle_recv_pdu(Domain, Addr, Vsn, Pdu, MS, ACM, - Logger, State); + maybe_handle_recv_pdu( + Domain, Addr, Vsn, Pdu, MS, ACM, Logger, State); {discarded, Reason, Report} -> ?vdebug("discarded: ~p", [Reason]), ErrorInfo = {failed_processing_message, Reason}, Pid ! {snmp_error, ErrorInfo, Domain, Addr}, - maybe_udp_send(Domain, Addr, Report, State), - ok; + maybe_udp_send(Domain, Addr, Report, State); {discarded, Reason} -> ?vdebug("discarded: ~p", [Reason]), ErrorInfo = {failed_processing_message, Reason}, - Pid ! {snmp_error, ErrorInfo, Domain, Addr}, - ok; + Pid ! {snmp_error, ErrorInfo, Domain, Addr}; Error -> error_msg("processing of received message failed: " - "~n ~p", [Error]), - ok + "~n ~p", [Error]) end. maybe_handle_recv_pdu( Domain, Addr, Vsn, #pdu{type = Type} = Pdu, PduMS, ACM, Logger, - #state{filter = FilterMod, domain = ManagerDomain} = State) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{filter = FilterMod, transports = Transports} = State) -> + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, Type)) of false -> - inc(netIfPduInDrops), - ok; + inc(netIfPduInDrops); _ -> handle_recv_pdu( Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State) end; maybe_handle_recv_pdu( Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, - #state{filter = FilterMod, domain = ManagerDomain} = State) + #state{filter = FilterMod, transports = Transports} = State) when is_record(Trap, trappdu) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, trappdu)) of false -> - inc(netIfPduInDrops), - ok; + inc(netIfPduInDrops); _ -> handle_recv_pdu( Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, State) @@ -625,40 +758,34 @@ handle_recv_pdu( #pdu{type = report} = Pdu, _PduMS, ok, _Logger, #state{server = Pid} = _State) -> ?vtrace("received report - ok", []), - Pid ! {snmp_report, {ok, Pdu}, Domain, Addr}, - ok; + Pid ! {snmp_report, {ok, Pdu}, Domain, Addr}; handle_recv_pdu( Domain, Addr, _Vsn, #pdu{type = report} = Pdu, _PduMS, {error, ReqId, Reason}, _Logger, #state{server = Pid} = _State) -> ?vtrace("received report - error", []), - Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Domain, Addr}, - ok; + Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Domain, Addr}; handle_recv_pdu( Domain, Addr, _Vsn, #pdu{type = 'snmpv2-trap'} = Pdu, _PduMS, _ACM, _Logger, #state{server = Pid} = _State) -> ?vtrace("received snmpv2-trap", []), - Pid ! {snmp_trap, Pdu, Domain, Addr}, - ok; + Pid ! {snmp_trap, Pdu, Domain, Addr}; handle_recv_pdu( Domain, Addr, _Vsn, Trap, _PduMS, _ACM, _Logger, #state{server = Pid} = _State) when is_record(Trap, trappdu) -> ?vtrace("received trappdu", []), - Pid ! {snmp_trap, Trap, Domain, Addr}, - ok; + Pid ! {snmp_trap, Trap, Domain, Addr}; handle_recv_pdu( Domain, Addr, _Vsn, Pdu, _PduMS, _ACM, _Logger, #state{server = Pid} = _State) when is_record(Pdu, pdu) -> ?vtrace("received pdu", []), - Pid ! {snmp_pdu, Pdu, Domain, Addr}, - ok; + Pid ! {snmp_pdu, Pdu, Domain, Addr}; handle_recv_pdu( _Domain, _Addr, _Vsn, Pdu, _PduMS, ACM, _Logger, _State) -> ?vlog("received unexpected pdu: " - "~n Pdu: ~p" - "~n ACM: ~p", [Pdu, ACM]), - ok. + "~n Pdu: ~p" + "~n ACM: ~p", [Pdu, ACM]). handle_inform_request( @@ -693,15 +820,29 @@ handle_inform_request( ok. handle_inform_response(Ref, Domain, Addr, State) -> - Verbosity = get(verbosity), - spawn_opt( - fun() -> - Log = worker_init(State, Verbosity), - Res = (catch do_handle_inform_response( - Ref, Domain, Addr, State#state{log = Log})), - worker_exit(inform_response, {Domain, Addr}, Res) + worker( + fun (S) -> + do_handle_inform_response(Ref, Domain, Addr, S) end, - [monitor]). + fun (Pid, Class, Reason, Stacktrace) -> + warning_msg( + "Worker process (~p) terminated " + "while processing (outgoing) inform response for %s:~n" + "~w:~w at ~p", + [Pid, snmp_conf:mk_addr_string({Domain, Addr}), + Class, Reason, Stacktrace]) + end, + State). + + %% Verbosity = get(verbosity), + %% spawn_opt( + %% fun() -> + %% Log = worker_init(State, Verbosity), + %% Res = (catch do_handle_inform_response( + %% Ref, Domain, Addr, State#state{log = Log})), + %% worker_exit(inform_response, {Domain, Addr}, Res) + %% end, + %% [monitor]). @@ -721,11 +862,11 @@ do_handle_inform_response(Ref, Domain, Addr, State) -> maybe_send_inform_response( RePdu, Vsn, ACM, Domain, Addr, Logger, - #state{server = Pid, - sock = Sock, - domain = ManagerDomain, - filter = FilterMod}) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{ + server = Pid, + filter = FilterMod, + transports = Transports} = State) -> + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_send_pdu( Arg1, Arg2, pdu_type_of(RePdu))) of @@ -735,8 +876,7 @@ maybe_send_inform_response( _ -> case snmpm_mpd:generate_response_msg(Vsn, RePdu, ACM, Logger) of {ok, Msg} -> - maybe_udp_send( - Domain, Addr, Msg, Sock, FilterMod, ManagerDomain); + maybe_udp_send(Domain, Addr, Msg, State); {discarded, Reason} -> ?vlog("failed generating response message:" "~n Reason: ~p", [Reason]), @@ -778,22 +918,36 @@ irgc_stop(Ref) -> handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State) -> - Verbosity = get(verbosity), - spawn_opt( - fun() -> - Log = worker_init(State, Verbosity), - Res = (catch maybe_handle_send_pdu( - Pdu, Vsn, MsgData, - Domain, Addr, - State#state{log = Log})), - worker_exit(send_pdu, {Domain, Addr}, Res) + worker( + fun (S) -> + maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, S) end, - [monitor]). + fun (Pid, Class, Reason, Stacktrace) -> + warning_msg( + "Worker process (~p) terminated " + "while processing (outgoing) pdu for %s:~n" + "~w:~w at ~p", + [Pid, snmp_conf:mk_addr_string({Domain, Addr}), + Class, Reason, Stacktrace]) + end, + State). + + %% Verbosity = get(verbosity), + %% spawn_opt( + %% fun() -> + %% Log = worker_init(State, Verbosity), + %% Res = (catch maybe_handle_send_pdu( + %% Pdu, Vsn, MsgData, + %% Domain, Addr, + %% State#state{log = Log})), + %% worker_exit(send_pdu, {Domain, Addr}, Res) + %% end, + %% [monitor]). maybe_handle_send_pdu( Pdu, Vsn, MsgData, Domain, Addr, - #state{filter = FilterMod, domain = ManagerDomain} = State) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{filter = FilterMod, transports = Transports} = State) -> + {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_send_pdu(Arg1, Arg2, pdu_type_of(Pdu))) of false -> inc(netIfPduOutDrops), @@ -804,9 +958,10 @@ maybe_handle_send_pdu( do_handle_send_pdu( Pdu, Vsn, MsgData, Domain, Addr, - #state{server = Pid, - note_store = NoteStore, - log = Log} = State) -> + #state{ + server = Pid, + note_store = NoteStore, + log = Log} = State) -> Logger = logger(Log, write, Domain, Addr), case (catch snmpm_mpd:generate_msg( Vsn, NoteStore, Pdu, MsgData, Logger)) of @@ -821,43 +976,55 @@ do_handle_send_pdu( ok end. + maybe_udp_send( Domain, Addr, Msg, - #state{sock = Sock, filter = FilterMod, domain = ManagerDomain}) -> - maybe_udp_send(Domain, Addr, Msg, Sock, FilterMod, ManagerDomain). - -maybe_udp_send(Domain, Addr, Msg, Sock, FilterMod, ManagerDomain) -> - {Arg1, Arg2} = fix_filter_address(ManagerDomain, {Domain, Addr}), + #state{filter = FilterMod, transports = Transports}) -> + To = {Domain, Addr}, + {Arg1, Arg2} = fix_filter_address(Transports, To), case (catch FilterMod:accept_send(Arg1, Arg2)) of false -> inc(netIfMsgOutDrops), ok; _ -> - %% XXX There should be some kind of lookup of socket - %% from transport domain here - {Ip, Port} = Addr, - udp_send(Sock, Ip, Port, Msg) + case select_transport_from_domain(Domain, Transports) of + false -> + error_msg( + "Can not find transport~n" + " size: ~p~n" + " to: ~s", + [sz(Msg), format_address(To)]); + #transport{socket = Socket} -> + udp_send(Socket, Addr, Msg) + end end. - - -udp_send(Sock, Ip, Port, Msg) -> - case (catch gen_udp:send(Sock, Ip, Port, Msg)) of + +udp_send(Sock, To, Msg) -> + {IpAddr, IpPort} = + case To of + {Domain, Addr} when is_atom(Domain) -> + Addr; + {_, P} = Addr when is_integer(P) -> + Addr + end, + try gen_udp:send(Sock, IpAddr, IpPort, Msg) of ok -> ?vdebug("sent ~w bytes to ~w:~w [~w]", - [sz(Msg), Ip, Port, Sock]), + [sz(Msg), IpAddr, IpPort, Sock]), ok; {error, Reason} -> - error_msg("failed sending message to ~p:~p: " - "~n ~p", [Ip, Port, Reason]), - ok; - Error -> - error_msg("failed sending message to ~p:~p: " - "~n ~p", [Ip, Port, Error]), - ok + error_msg("failed sending message to ~p:~p:~n" + " ~p",[IpAddr, IpPort, Reason]) + catch + error:Error -> + error_msg("failed sending message to ~p:~p:~n" + " error:~p~n" + " ~p", + [IpAddr, IpPort, Error, erlang:get_stacktrace()]) end. sz(B) when is_binary(B) -> - size(B); + byte_size(B); sz(L) when is_list(L) -> length(L); sz(_) -> @@ -1047,79 +1214,152 @@ handle_set_log_type(State, _NewType) -> {State, {error, not_enabled}}. -%% ------------------------------------------------------------------- - -worker_init(#state{log = undefined = Log}, Verbosity) -> - worker_init2(Log, Verbosity); -worker_init(#state{log = {Name, Log, Type}}, Verbosity) -> - case snmp_log:open(Name, Log) of - {ok, NewLog} -> - worker_init2({Name, NewLog, Type}, Verbosity); - {error, Reason} -> - warning_msg("NetIf worker ~p failed opening ATL: " - "~n ~p", [self(), Reason]), - NewLog = undefined, - worker_init2({Name, NewLog, Type}, Verbosity) - end; -worker_init(State, Verbosity) -> - ?vinfo("worker_init -> entry with invalid data: " - "~n State: ~p" - "~n Verbosity: ~p", [State, Verbosity]), - exit({worker_init, State, Verbosity}). - -worker_init2(Log, Verbosity) -> - put(sname, mnifw), - put(verbosity, Verbosity), - Log. - - -worker_exit(Tag, Info, Result) -> - exit({net_if_worker, {Tag, Info, Result}}). - -handle_worker_exit(_, {_, _, ok}) -> - ok; -handle_worker_exit(Pid, {udp, {Domain, Addr}, ExitStatus}) -> - warning_msg( - "Worker process (~p) terminated " - "while processing (incomming) message from %s:~n" - "~p", [Pid, snmp_conf:mk_addr_string({Domain, Addr}), ExitStatus]), - ok; -handle_worker_exit(Pid, {send_pdu, {Domain, Addr}, ExitStatus}) -> - warning_msg( - "Worker process (~p) terminated " - "while processing (outgoing) pdu for %s:~n" - "~p", [Pid, snmp_conf:mk_addr_string({Domain, Addr}), ExitStatus]), - ok; -handle_worker_exit(Pid, {inform_response, {Domain, Addr}, ExitStatus}) -> - warning_msg( - "Worker process (~p) terminated " - "while processing (outgoing) inform response for %s:~n" - "~p", [Pid, snmp_conf:mk_addr_string({Domain, Addr}), ExitStatus]), - ok; -handle_worker_exit(_, _) -> - ok. - +select_transport_from_domain(Domain, Transports) when is_atom(Domain) -> + Pos = #transport.domain, + case lists:keyfind(Domain, Pos, Transports) of + #transport{domain = Domain} = Transport -> + Transport; + false when Domain == snmpUDPDomain -> + lists:keyfind(transportDomainUdpIpv4, Pos, Transports); + false when Domain == transportDomainUdpIpv4 -> + lists:keyfind(snmpUDPDomain, Pos, Transports); + false -> + false + end. %% If the manager uses legacy snmpUDPDomain e.g has not set %% {domain, _}, then make sure snmpm_network_interface_filter %% gets legacy arguments to not break backwards compatibility. %% -fix_filter_address(snmpUDPDomain, {Domain, Addr}) - when Domain =:= snmpUDPDomain; - Domain =:= transportDomainUdpIpv4 -> - Addr; -fix_filter_address(_ManagerDomain, {Domain, _} = Address) - when is_atom(Domain) -> - Address; -fix_filter_address(snmpUDPDomain, {_, Port} = Addr) - when is_integer(Port) -> - Addr. +fix_filter_address(Transports, Address) -> + DefaultDomain = snmpm_config:default_transport_domain(), + case Transports of + [#transport{domain = DefaultDomain}, DefaultDomain] -> + case Address of + {Domain, Addr} when is_atom(Domain) -> + Addr; + {_, IpPort} = Addr when is_integer(IpPort) -> + Addr + end; + _ -> + Address + end. address(Domain, Addr) when is_atom(Domain) -> {Domain, Addr}; address(Ip, Port) when is_integer(Port) -> {snmpm_config:default_transport_domain(), {Ip, Port}}. +format_address(Address) -> + iolist_to_binary(snmp_conf:mk_addr_string(Address)). + +%% ------------------------------------------------------------------- + +worker(Worker, Failer, State) -> + Verbosity = get(verbosity), + spawn_opt( + fun () -> + try + put(sname, mnifw), + put(verbosity, Verbosity), + Worker(worker_init(State)) + of + Result -> + %% Winds up in handle_info {'DOWN', ...} + erlang:exit({net_if_worker, Result}) + catch + Class:Reason -> + %% Winds up in handle_info {'DOWN', ...} + erlang:exit( + {net_if_worker, Failer, + Class, Reason, erlang:get_stacktrace()}) + end + end, + [monitor]). + +worker_init(#state{log = undefined} = State) -> + State; +worker_init(#state{log = {Name, Log, Type}} = State) -> + case snmp_log:open(Name, Log) of + {ok, NewLog} -> + State#state{log = {Name, NewLog, Type}}; + {error, Reason} -> + warning_msg("NetIf worker ~p failed opening ATL: " + "~n ~p", [self(), Reason]), + State#state{log = {Name, undefined, Type}} + end; +worker_init(State) -> + ?vinfo("worker_init -> entry with invalid data: " + "~n State: ~p", [State]), + erlang:error({worker_init, State}). + +%% worker_init2(Log, Verbosity) -> +%% put(sname, mnifw), +%% put(verbosity, Verbosity), +%% Log. + + +%% worker_exit(Tag, Info, Result) -> +%% exit({net_if_worker, {Tag, Info, Result}}). + +%% handle_worker_exit(_, {_, _, {Result}}) -> +%% Result; +%% handle_worker_exit( +%% Pid, {udp, {Domain, Addr}, {Class, Reason, Stacktrace}) -> +%% warning_msg( +%% "Worker process (~p) terminated " +%% "while processing (incomming) message from %s:~n" +%% "~w:~w at ~p", +%% [Pid, snmp_conf:mk_addr_string({Domain, Addr}), +%% Class, Reason, Stacktrace]), +%% ok; +%% handle_worker_exit( +%% Pid, {send_pdu, {Domain, Addr}, {Class, Reason, Stacktrace}) -> +%% warning_msg( +%% "Worker process (~p) terminated " +%% "while processing (outgoing) pdu for %s:~n" +%% "~w:~w at ~p", +%% [Pid, snmp_conf:mk_addr_string({Domain, Addr}), +%% Class, Reason, Stacktrace]), +%% ok; +%% handle_worker_exit( +%% Pid, {inform_response, {Domain, Addr}, {Class, Reason, Stacktrace}}) -> +%% warning_msg( +%% "Worker process (~p) terminated " +%% "while processing (outgoing) inform response for %s:~n" +%% "~w:~w at ~p", +%% [Pid, snmp_conf:mk_addr_string({Domain, Addr}), +%% Class, Reason, Stacktrace]), +%% ok; +%% handle_worker_exit(Pid, Term) -> +%% warning_msg( +%% "Worker process (~p) terminated for strange reason: ~p", +%% [Pid, Term]). + + +%% %% If the manager uses legacy snmpUDPDomain e.g has not set +%% %% {domain, _}, then make sure snmpm_network_interface_filter +%% %% gets legacy arguments to not break backwards compatibility. +%% %% +%% fix_filter_address(snmpUDPDomain, {Domain, Addr}) +%% when Domain =:= snmpUDPDomain; +%% Domain =:= transportDomainUdpIpv4 -> +%% Addr; +%% fix_filter_address(_ManagerDomain, {Domain, _} = Address) +%% when is_atom(Domain) -> +%% Address; +%% fix_filter_address(snmpUDPDomain, {_, Port} = Addr) +%% when is_integer(Port) -> +%% Addr. + +%% address(Domain, Addr) when is_atom(Domain) -> +%% {Domain, Addr}; +%% address(Ip, Port) when is_integer(Port) -> +%% {snmpm_config:default_transport_domain(), {Ip, Port}}. + +%% format_address(Address) -> +%% iolist_to_binary(snmp_conf:mk_addr_string(Address)). + %% ------------------------------------------------------------------- make_response_pdu(#pdu{request_id = ReqId, varbinds = Vbs}) -> @@ -1170,7 +1410,7 @@ logger({_Name, Log, Types}, Type, Domain, Addr) -> AddrString = iolist_to_binary(snmp_conf:mk_addr_string({Domain, Addr})), fun(Msg) -> - snmp_log:log(Log, Msg, Domain, AddrString) + snmp_log:log(Log, Msg, AddrString) end; false -> fun(_) -> @@ -1205,10 +1445,11 @@ get_opt(Opts, Key, Def) -> %% ------------------------------------------------------------------- -get_info(#state{sock = Id}) -> +get_info(#state{transports = Transports}) -> ProcSize = proc_mem(self()), - PortInfo = get_port_info(Id), - [{process_memory, ProcSize}, {port_info, PortInfo}]. + [{process_memory, ProcSize} + | [{port_info, get_port_info(Socket)} + || #transport{socket = Socket} <- Transports]]. proc_mem(P) when is_pid(P) -> case (catch erlang:process_info(P, memory)) of diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl index 5ce9cf9e5c..c514eafd7d 100644 --- a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl @@ -60,16 +60,19 @@ groups() -> [{ipv4, [], [{group, snmpget}, {group, snmptrapd}, + {group, snmpd_mt}, {group, snmpd} ]}, {ipv6, [], [{group, snmpget}, {group, snmptrapd}, + {group, snmpd_mt}, {group, snmpd} ]}, {ipv4_ipv6, [], [{group, snmpget}, {group, snmptrapd}, + {group, snmpd_mt}, {group, snmpd} ]}, %% @@ -77,6 +80,8 @@ groups() -> [erlang_agent_netsnmp_get]}, {snmptrapd, [], [erlang_agent_netsnmp_inform]}, + {snmpd_mt, [], + [erlang_manager_netsnmp_get]}, {snmpd, [], [erlang_manager_netsnmp_get]} ]. @@ -100,9 +105,16 @@ init_per_group(snmpget = Exec, Config) -> init_per_group(snmptrapd = Exec, Config) -> %% From Ubuntu package snmpd init_per_group_agent(Exec, Config); +init_per_group(snmpd_mt, Config) -> + %% From Ubuntu package snmp + init_per_group_manager( + snmpd, + [{manager_net_if_module, snmpm_net_if_mt} | Config]); init_per_group(snmpd = Exec, Config) -> %% From Ubuntu package snmp - init_per_group_manager(Exec, Config); + init_per_group_manager( + Exec, + [{manager_net_if_module, snmpm_net_if} | Config]); %% init_per_group(_, Config) -> Config. @@ -462,10 +474,12 @@ agent_app_env(Config) -> manager_app_env(Config) -> Dir = ?config(priv_dir, Config), Vsns = ?config(snmp_versions, Config), + NetIfModule = ?config(manager_net_if_module, Config), [{versions, Vsns}, {audit_trail_log, [{type, read_write}, {dir, Dir}, {size, {10240, 10}}]}, + {net_if, [{module, NetIfModule}]}, {config, [{dir, Dir}, {db_dir, Dir}, {verbosity, trace}]} -- cgit v1.2.3 From 037590364fe8b5a657563cd7d28a20d84ee8d99f Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Wed, 20 Aug 2014 12:15:46 +0200 Subject: Remove decommented code and clean up diff --- lib/snmp/src/manager/snmpm_net_if.erl | 154 ++++------------------ lib/snmp/src/manager/snmpm_net_if_mt.erl | 217 +------------------------------ 2 files changed, 28 insertions(+), 343 deletions(-) diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl index c4716dfd21..bdde8a5623 100644 --- a/lib/snmp/src/manager/snmpm_net_if.erl +++ b/lib/snmp/src/manager/snmpm_net_if.erl @@ -59,8 +59,6 @@ { server, note_store, -%% domain, -%% sock, transports = [], mpd_state, log, @@ -170,12 +168,6 @@ init([Server, NoteStore]) -> {error, Reason} -> {stop, Reason} end. - %% case (catch do_init(Server, NoteStore)) of - %% {error, Reason} -> - %% {stop, Reason}; - %% {ok, State} -> - %% {ok, State} - %% end. do_init(Server, NoteStore) -> process_flag(trap_exit, true), @@ -190,8 +182,8 @@ do_init(Server, NoteStore) -> %% -- Verbosity -- {ok, Verbosity} = snmpm_config:system_info(net_if_verbosity), - put(sname,mnif), - put(verbosity,Verbosity), + put(sname, mnif), + put(verbosity, Verbosity), ?vlog("starting", []), %% -- MPD -- @@ -246,74 +238,6 @@ do_init(Server, NoteStore) -> ?vdebug("started", []), {ok, State} end. - - - - %% %% -- Socket -- - %% SndBuf = get_opt(Opts, sndbuf, default), - %% RecBuf = get_opt(Opts, recbuf, default), - %% BindTo = get_opt(Opts, bind_to, false), - %% NoReuse = get_opt(Opts, no_reuse, false), - - %% {ok, Port} = snmpm_config:system_info(port), - %% Domain = - %% case snmpm_config:system_info(domain) of - %% {ok, D} -> - %% D; - %% _ -> - %% snmpm_config:default_transport_domain() - %% end, - %% {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, Domain, BindTo, NoReuse), - - %% %% -- Initiate counters --- - %% init_counters(), - - %% %% -- We are done --- - %% State = #state{server = Server, - %% note_store = NoteStore, - %% mpd_state = MpdState, - %% domain = Domain, - %% sock = Sock, - %% log = Log, - %% irb = IRB, - %% irgc = IrGcRef, - %% filter = FilterMod}, - %% ?vdebug("started", []), - %% {ok, State}. - - -%% %% Open port -%% do_open_port(Port, SendSz, RecvSz, Domain, BindTo, NoReuse) -> -%% ?vtrace("do_open_port -> entry with~n" -%% " Port: ~p~n" -%% " SendSz: ~p~n" -%% " RecvSz: ~p~n" -%% " Domain: ~p~n" -%% " BindTo: ~p~n" -%% " NoReuse: ~p", -%% [Port, SendSz, RecvSz, Domain, BindTo, NoReuse]), -%% IpOpts1 = bind_to(BindTo), -%% IpOpts2 = no_reuse(NoReuse), -%% IpOpts3 = recbuf(RecvSz), -%% IpOpts4 = sndbuf(SendSz), -%% IpOpts = -%% [binary, -%% snmp_conf:tdomain_to_family(Domain) | -%% IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], -%% OpenRes = -%% case init:get_argument(snmpm_fd) of -%% {ok, [[FdStr]]} -> -%% Fd = list_to_integer(FdStr), -%% gen_udp:open(0, [{fd, Fd}|IpOpts]); -%% error -> -%% gen_udp:open(Port, IpOpts) -%% end, -%% case OpenRes of -%% {error, _} = Error -> -%% throw(Error); -%% OK -> -%% OK -%% end. socket_open(IpPort, SocketOpts) -> ?vtrace("socket_open -> entry with~n" @@ -326,18 +250,6 @@ socket_open(IpPort, SocketOpts) -> Socket end. -%% bind_to(true) -> -%% case snmpm_config:system_info(address) of -%% {ok, Addr} when is_list(Addr) -> -%% [{ip, list_to_tuple(Addr)}]; -%% {ok, Addr} -> -%% [{ip, Addr}]; -%% _ -> -%% [] -%% end; -%% bind_to(_) -> -%% []. - socket_params(Domain, {IpAddr, IpPort}, BindTo, CommonSocketOpts) -> Family = snmp_conf:tdomain_to_family(Domain), SocketOpts = @@ -391,21 +303,6 @@ common_socket_opts(Opts) -> [] end]. -%% no_reuse(false) -> -%% [{reuseaddr, true}]; -%% no_reuse(_) -> -%% []. - -%% recbuf(default) -> -%% []; -%% recbuf(Sz) -> -%% [{recbuf, Sz}]. - -%% sndbuf(default) -> -%% []; -%% sndbuf(Sz) -> -%% [{sndbuf, Sz}]. - create_filter(Opts) when is_list(Opts) -> case get_opt(Opts, module, ?DEFAULT_FILTER_MODULE) of @@ -419,6 +316,10 @@ create_filter(BadOpts) -> throw({error, {bad_filter_opts, BadOpts}}). +%% ---------------------------------------------------------------------- +%% Audit Trail Logger +%% ---------------------------------------------------------------------- + %% Open log do_init_log(false) -> ?vtrace("do_init_log(false) -> entry", []), @@ -439,8 +340,8 @@ do_init_log(true) -> Function = increment_counter, Args = [atl_seqno, Initial, Max], SeqNoGen = {Module, Function, Args}, - case snmp_log:create(Name, File, - SeqNoGen, Size, Repair, true) of + case snmp_log:create( + Name, File, SeqNoGen, Size, Repair, true) of {ok, Log} -> ?vdebug("log created: ~w", [Log]), {Log, Type}; @@ -518,7 +419,7 @@ handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo}, " Vsn: ~p~n" " MsgData: ~p~n" " Domain: ~p~n" - " Addr : ~p", [Pdu, Vsn, MsgData, Domain, Addr]), + " Addr: ~p", [Pdu, Vsn, MsgData, Domain, Addr]), maybe_process_extra_info(ExtraInfo), maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State), {noreply, State}; @@ -625,18 +526,17 @@ maybe_handle_recv_msg( case (catch FilterMod:accept_recv(Arg1, Arg2)) of false -> %% Drop the received packet - inc(netIfMsgInDrops), - ok; + inc(netIfMsgInDrops); _ -> handle_recv_msg(Domain, Addr, Bytes, State) - end. + end, + ok. handle_recv_msg(Domain, Addr, Bytes, #state{server = Pid}) when is_binary(Bytes) andalso (size(Bytes) =:= 0) -> - Pid ! {snmp_error, {empty_message, Domain, Addr}, Domain, Addr}, - ok; - + Pid ! {snmp_error, {empty_message, Domain, Addr}, Domain, Addr}; +%% handle_recv_msg( Domain, Addr, Bytes, #state{ @@ -645,30 +545,27 @@ handle_recv_msg( mpd_state = MpdState, log = Log} = State) -> Logger = logger(Log, read, Domain, Addr), - case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, - MpdState, NoteStore, Logger)) of + case (catch snmpm_mpd:process_msg( + Bytes, Domain, Addr, MpdState, NoteStore, Logger)) of {ok, Vsn, Pdu, MS, ACM} -> - maybe_handle_recv_pdu(Domain, Addr, Vsn, Pdu, MS, ACM, - Logger, State); + maybe_handle_recv_pdu( + Domain, Addr, Vsn, Pdu, MS, ACM, Logger, State); {discarded, Reason, Report} -> ?vdebug("discarded: ~p", [Reason]), ErrorInfo = {failed_processing_message, Reason}, Pid ! {snmp_error, ErrorInfo, Domain, Addr}, - maybe_udp_send(Domain, Addr, Report, State), - ok; + maybe_udp_send(Domain, Addr, Report, State); {discarded, Reason} -> ?vdebug("discarded: ~p", [Reason]), ErrorInfo = {failed_processing_message, Reason}, - Pid ! {snmp_error, ErrorInfo, Domain, Addr}, - ok; + Pid ! {snmp_error, ErrorInfo, Domain, Addr}; Error -> error_msg("processing of received message failed: " - "~n ~p", [Error]), - ok + "~n ~p", [Error]) end. @@ -678,8 +575,7 @@ maybe_handle_recv_pdu( {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, Type)) of false -> - inc(netIfPduInDrops), - ok; + inc(netIfPduInDrops); _ -> handle_recv_pdu( Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State) @@ -691,8 +587,7 @@ maybe_handle_recv_pdu( {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, trappdu)) of false -> - inc(netIfPduInDrops), - ok; + inc(netIfPduInDrops); _ -> handle_recv_pdu( Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, State) @@ -809,8 +704,7 @@ maybe_send_inform_response( "~n Reason: ~p", [Reason]), ReqId = RePdu#pdu.request_id, ErrorInfo = {failed_generating_response, {RePdu, Reason}}, - Pid ! {snmp_error, ReqId, ErrorInfo, Domain, Addr}, - ok + Pid ! {snmp_error, ReqId, ErrorInfo, Domain, Addr} end end. diff --git a/lib/snmp/src/manager/snmpm_net_if_mt.erl b/lib/snmp/src/manager/snmpm_net_if_mt.erl index 516a2f444a..8f2ed6d8cd 100644 --- a/lib/snmp/src/manager/snmpm_net_if_mt.erl +++ b/lib/snmp/src/manager/snmpm_net_if_mt.erl @@ -59,8 +59,6 @@ { server, note_store, -%% domain, -%% sock, transports = [], mpd_state, log, @@ -170,12 +168,6 @@ init([Server, NoteStore]) -> {error, Reason} -> {stop, Reason} end. - %% case (catch do_init(Server, NoteStore)) of - %% {error, Reason} -> - %% {stop, Reason}; - %% {ok, State} -> - %% {ok, State} - %% end. do_init(Server, NoteStore) -> process_flag(trap_exit, true), @@ -192,7 +184,7 @@ do_init(Server, NoteStore) -> %% -- Verbosity -- {ok, Verbosity} = snmpm_config:system_info(net_if_verbosity), - put(sname, mnif), + put(sname, mnif), put(verbosity, Verbosity), ?vlog("starting", []), @@ -251,74 +243,6 @@ do_init(Server, NoteStore) -> {ok, State} end. - - - %% %% -- Socket -- - %% SndBuf = get_opt(Opts, sndbuf, default), - %% RecBuf = get_opt(Opts, recbuf, default), - %% BindTo = get_opt(Opts, bind_to, false), - %% NoReuse = get_opt(Opts, no_reuse, false), - - %% {ok, Port} = snmpm_config:system_info(port), - %% Domain = - %% case snmpm_config:system_info(domain) of - %% {ok, D} -> - %% D; - %% _ -> - %% snmpm_config:default_transport_domain() - %% end, - %% {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, Domain, BindTo, NoReuse), - - %% %% -- Initiate counters --- - %% init_counters(), - - %% %% -- We are done --- - %% State = #state{server = Server, - %% note_store = NoteStore, - %% mpd_state = MpdState, - %% domain = Domain, - %% sock = Sock, - %% log = Log, - %% irb = IRB, - %% irgc = IrGcRef, - %% filter = FilterMod}, - %% ?vdebug("started", []), - %% {ok, State}. - - -%% %% Open port -%% do_open_port(Port, SendSz, RecvSz, Domain, BindTo, NoReuse) -> -%% ?vtrace("do_open_port -> entry with~n" -%% " Port: ~p~n" -%% " SendSz: ~p~n" -%% " RecvSz: ~p~n" -%% " Domain: ~p~n" -%% " BindTo: ~p~n" -%% " NoReuse: ~p", -%% [Port, SendSz, RecvSz, Domain, BindTo, NoReuse]), -%% IpOpts1 = bind_to(BindTo), -%% IpOpts2 = no_reuse(NoReuse), -%% IpOpts3 = recbuf(RecvSz), -%% IpOpts4 = sndbuf(SendSz), -%% IpOpts = -%% [binary, -%% snmp_conf:tdomain_to_family(Domain) | -%% IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], -%% OpenRes = -%% case init:get_argument(snmpm_fd) of -%% {ok, [[FdStr]]} -> -%% Fd = list_to_integer(FdStr), -%% gen_udp:open(0, [{fd, Fd}|IpOpts]); -%% error -> -%% gen_udp:open(Port, IpOpts) -%% end, -%% case OpenRes of -%% {error, _} = Error -> -%% throw(Error); -%% OK -> -%% OK -%% end. - socket_open(IpPort, SocketOpts) -> ?vtrace("socket_open -> entry with~n" " IpPort: ~p~n" @@ -330,18 +254,6 @@ socket_open(IpPort, SocketOpts) -> Socket end. -%% bind_to(true) -> -%% case snmpm_config:system_info(address) of -%% {ok, Addr} when is_list(Addr) -> -%% [{ip, list_to_tuple(Addr)}]; -%% {ok, Addr} -> -%% [{ip, Addr}]; -%% _ -> -%% [] -%% end; -%% bind_to(_) -> -%% []. - socket_params(Domain, {IpAddr, IpPort}, BindTo, CommonSocketOpts) -> Family = snmp_conf:tdomain_to_family(Domain), SocketOpts = @@ -395,21 +307,6 @@ common_socket_opts(Opts) -> [] end]. -%% no_reuse(false) -> -%% [{reuseaddr, true}]; -%% no_reuse(_) -> -%% []. - -%% recbuf(default) -> -%% []; -%% recbuf(Sz) -> -%% [{recbuf, Sz}]. - -%% sndbuf(default) -> -%% []; -%% sndbuf(Sz) -> -%% [{sndbuf, Sz}]. - create_filter(Opts) when is_list(Opts) -> case get_opt(Opts, module, ?DEFAULT_FILTER_MODULE) of @@ -615,7 +512,7 @@ terminate(Reason, #state{log = Log, irgc = IrGcRef}) -> ok. -do_close_log({Log, _Type}) -> +do_close_log({_Name, Log, _Type}) -> (catch snmp_log:sync(Log)), (catch snmp_log:close(Log)), ok; @@ -656,19 +553,6 @@ handle_udp(Domain, Addr, Bytes, State) -> end, State). - %% Verbosity = get(verbosity), - %% spawn_opt( - %% fun() -> - %% Log = worker_init(State, Verbosity), - %% Res = - %% (catch maybe_handle_recv_msg( - %% Domain, Addr, Bytes, - %% State#state{log = Log})), - %% worker_exit(udp, {Domain, Addr}, Res) - %% end, - %% [monitor]). - - maybe_handle_recv_msg( Domain, Addr, Bytes, #state{filter = FilterMod, transports = Transports} = State) -> @@ -816,8 +700,7 @@ handle_inform_request( Expire = t() + To, Rec = {Key, Expire, {Vsn, ACM, RePdu}}, ets:insert(snmpm_inform_request_table, Rec) - end, - ok. + end. handle_inform_response(Ref, Domain, Addr, State) -> worker( @@ -834,18 +717,6 @@ handle_inform_response(Ref, Domain, Addr, State) -> end, State). - %% Verbosity = get(verbosity), - %% spawn_opt( - %% fun() -> - %% Log = worker_init(State, Verbosity), - %% Res = (catch do_handle_inform_response( - %% Ref, Domain, Addr, State#state{log = Log})), - %% worker_exit(inform_response, {Domain, Addr}, Res) - %% end, - %% [monitor]). - - - do_handle_inform_response(Ref, Domain, Addr, State) -> Key = {Ref, Domain, Addr}, case ets:lookup(snmpm_inform_request_table, Key) of @@ -882,8 +753,7 @@ maybe_send_inform_response( "~n Reason: ~p", [Reason]), ReqId = RePdu#pdu.request_id, ErrorInfo = {failed_generating_response, {RePdu, Reason}}, - Pid ! {snmp_error, ReqId, ErrorInfo, Domain, Addr}, - ok + Pid ! {snmp_error, ReqId, ErrorInfo, Domain, Addr} end end. @@ -932,18 +802,6 @@ handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State) -> end, State). - %% Verbosity = get(verbosity), - %% spawn_opt( - %% fun() -> - %% Log = worker_init(State, Verbosity), - %% Res = (catch maybe_handle_send_pdu( - %% Pdu, Vsn, MsgData, - %% Domain, Addr, - %% State#state{log = Log})), - %% worker_exit(send_pdu, {Domain, Addr}, Res) - %% end, - %% [monitor]). - maybe_handle_send_pdu( Pdu, Vsn, MsgData, Domain, Addr, #state{filter = FilterMod, transports = Transports} = State) -> @@ -1293,73 +1151,6 @@ worker_init(State) -> "~n State: ~p", [State]), erlang:error({worker_init, State}). -%% worker_init2(Log, Verbosity) -> -%% put(sname, mnifw), -%% put(verbosity, Verbosity), -%% Log. - - -%% worker_exit(Tag, Info, Result) -> -%% exit({net_if_worker, {Tag, Info, Result}}). - -%% handle_worker_exit(_, {_, _, {Result}}) -> -%% Result; -%% handle_worker_exit( -%% Pid, {udp, {Domain, Addr}, {Class, Reason, Stacktrace}) -> -%% warning_msg( -%% "Worker process (~p) terminated " -%% "while processing (incomming) message from %s:~n" -%% "~w:~w at ~p", -%% [Pid, snmp_conf:mk_addr_string({Domain, Addr}), -%% Class, Reason, Stacktrace]), -%% ok; -%% handle_worker_exit( -%% Pid, {send_pdu, {Domain, Addr}, {Class, Reason, Stacktrace}) -> -%% warning_msg( -%% "Worker process (~p) terminated " -%% "while processing (outgoing) pdu for %s:~n" -%% "~w:~w at ~p", -%% [Pid, snmp_conf:mk_addr_string({Domain, Addr}), -%% Class, Reason, Stacktrace]), -%% ok; -%% handle_worker_exit( -%% Pid, {inform_response, {Domain, Addr}, {Class, Reason, Stacktrace}}) -> -%% warning_msg( -%% "Worker process (~p) terminated " -%% "while processing (outgoing) inform response for %s:~n" -%% "~w:~w at ~p", -%% [Pid, snmp_conf:mk_addr_string({Domain, Addr}), -%% Class, Reason, Stacktrace]), -%% ok; -%% handle_worker_exit(Pid, Term) -> -%% warning_msg( -%% "Worker process (~p) terminated for strange reason: ~p", -%% [Pid, Term]). - - -%% %% If the manager uses legacy snmpUDPDomain e.g has not set -%% %% {domain, _}, then make sure snmpm_network_interface_filter -%% %% gets legacy arguments to not break backwards compatibility. -%% %% -%% fix_filter_address(snmpUDPDomain, {Domain, Addr}) -%% when Domain =:= snmpUDPDomain; -%% Domain =:= transportDomainUdpIpv4 -> -%% Addr; -%% fix_filter_address(_ManagerDomain, {Domain, _} = Address) -%% when is_atom(Domain) -> -%% Address; -%% fix_filter_address(snmpUDPDomain, {_, Port} = Addr) -%% when is_integer(Port) -> -%% Addr. - -%% address(Domain, Addr) when is_atom(Domain) -> -%% {Domain, Addr}; -%% address(Ip, Port) when is_integer(Port) -> -%% {snmpm_config:default_transport_domain(), {Ip, Port}}. - -%% format_address(Address) -> -%% iolist_to_binary(snmp_conf:mk_addr_string(Address)). - %% ------------------------------------------------------------------- make_response_pdu(#pdu{request_id = ReqId, varbinds = Vbs}) -> -- cgit v1.2.3 From bdbd6849aa811faf20d5ce7d577a49612266209a Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Fri, 22 Aug 2014 12:09:03 +0200 Subject: Clean up config error handling and negative results --- lib/snmp/src/agent/snmp_target_mib.erl | 15 +++++++++++++++ lib/snmp/src/agent/snmpa_conf.erl | 23 ++++++++++++++--------- lib/snmp/src/manager/snmpm_config.erl | 7 ++++++- lib/snmp/src/misc/snmp_conf.erl | 8 +++++--- lib/snmp/src/misc/snmp_config.erl | 8 ++++++-- lib/snmp/test/snmp_manager_config_test.erl | 2 +- 6 files changed, 47 insertions(+), 16 deletions(-) diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl index e916f17d6a..df694ed16b 100644 --- a/lib/snmp/src/agent/snmp_target_mib.erl +++ b/lib/snmp/src/agent/snmp_target_mib.erl @@ -181,6 +181,10 @@ check_target_addr( check_target_addr( Name, Domain, Address, Timeout, RetryCount, TagList, Params, EngineId, TMask, MMS); +check_target_addr( + {_Name, Domain, Address, _Timeout, _RetryCount, _TagList, _Params, + _EngineId, _TMask, _MMS}) -> % Arity 10 + error({bad_address, {Domain, Address}}); check_target_addr( {Name, Domain, Address, Timeout, RetryCount, TagList, Params, EngineId}) % Arity 8 @@ -197,6 +201,10 @@ check_target_addr( check_target_addr( Name, Domain, Address, Timeout, RetryCount, TagList, Params, EngineId); +check_target_addr( + {_Name, Domain, Address, _Timeout, _RetryCount, _TagList, _Params, + _EngineId}) ->% Arity 8 + error({bad_address, {Domain, Address}}); %% Use dummy engine id if the old style is found check_target_addr( {Name, Domain, Address, Timeout, RetryCount, TagList, Params}) % Arity 7 @@ -210,6 +218,9 @@ check_target_addr( Address = {Ip, Udp}, check_target_addr( Name, Domain, Address, Timeout, RetryCount, TagList, Params); +check_target_addr( + {_Name, Domain, Address, _Timeout, _RetryCount, _TagList, _Params}) -> % Arity 7 + error({bad_address, {Domain, Address}}); %% Use dummy engine id if the old style is found check_target_addr( {Name, Domain, Address, Timeout, RetryCount, TagList, Params, @@ -225,6 +236,10 @@ check_target_addr( Address = {Ip, Udp}, check_target_addr( Name, Domain, Address, Timeout, RetryCount, TagList, Params, TMask, MMS); +check_target_addr( + {_Name, Domain, Address, _Timeout, _RetryCount, _TagList, _Params, + _TMask, _MMS}) -> % Arity 9 + error({bad_address, {Domain, Address}}); check_target_addr(X) -> error({invalid_target_addr, X}). diff --git a/lib/snmp/src/agent/snmpa_conf.erl b/lib/snmp/src/agent/snmpa_conf.erl index b4d32dc928..fe3f63c4ca 100644 --- a/lib/snmp/src/agent/snmpa_conf.erl +++ b/lib/snmp/src/agent/snmpa_conf.erl @@ -473,6 +473,16 @@ write_target_addr_conf(Fd, Conf) -> lists:foreach(Fun, Conf), ok. +do_write_target_addr_conf( + Fd, + {Name, Domain, Address, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize}) + when is_atom(Domain) -> + io:format( + Fd, + "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", + [Name, Domain, Address, Timeout, RetryCount, TagList, + ParamsName, EngineId, TMask, MaxMessageSize]); do_write_target_addr_conf( Fd, {Name, Ip, Udp, Timeout, RetryCount, TagList, @@ -485,15 +495,10 @@ do_write_target_addr_conf( {Name, Domain, Address, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}); do_write_target_addr_conf( - Fd, - {Name, Domain, Address, Timeout, RetryCount, TagList, - ParamsName, EngineId, TMask, MaxMessageSize}) - when is_atom(Domain) -> - io:format( - Fd, - "{\"~s\", ~w, ~w, ~w, ~w, \"~s\", \"~s\", \"~s\", ~w, ~w}.~n", - [Name, Domain, Address, Timeout, RetryCount, TagList, - ParamsName, EngineId, TMask, MaxMessageSize]); + _Fd, + {_Name, Domain, Address, _Timeout, _RetryCount, _TagList, + _ParamsName, _EngineId, _TMask, _MaxMessageSize}) -> + error({bad_address, {Domain, Address}}); do_write_target_addr_conf( Fd, {Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index d147aabb0b..05d5ce72b1 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -461,7 +461,7 @@ agent_info(Domain, Address, Item) when is_atom(Domain) -> [Domain, Address, Item, _Thrown, erlang:get_stacktrace()]), {error, not_found} end; -agent_info(Ip, Port, Item) -> +agent_info(Ip, Port, Item) when is_integer(Port) -> p(?MODULE_STRING":agent_info(~p, ~p, ~p) entry~n", [Ip, Port, Item]), Domain = default_transport_domain(), @@ -1698,6 +1698,11 @@ check_agent_config( UserId, TargetName, Community, Domain, Addr, EngineId, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel); +check_agent_config( + {_UserId, _TargetName, _Community, Domain, Addr, + _EngineId, _Timeout, _MaxMessageSize, + _Version, _SecModel, _SecName, _SecLevel}) -> + error({bad_address, {Domain, Addr}}); check_agent_config( {UserId, TargetName, Community, Domain, Ip, Port, EngineId, Timeout, MaxMessageSize, diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl index f4483995cb..153c8070c2 100644 --- a/lib/snmp/src/misc/snmp_conf.erl +++ b/lib/snmp/src/misc/snmp_conf.erl @@ -749,8 +749,6 @@ which_domain({A0, A1, A2, A3, A4, A5, A6, A7}) %% --------- -mk_addr_string({_IP, Port} = Addr) when is_integer(Port) -> - mk_addr_string({snmpUDPDomain, Addr}); mk_addr_string({Domain, Addr}) when is_atom(Domain) -> %% XXX There is only code for IP domains here case check_address_ip(Domain, Addr) of @@ -768,7 +766,11 @@ mk_addr_string({Domain, Addr}) when is_atom(Domain) -> mk_addr_string_ntoa(Domain, Addr); IP -> mk_addr_string_ntoa(Domain, IP) - end. + end; +mk_addr_string({_IP, Port} = Addr) when is_integer(Port) -> + mk_addr_string({snmpUDPDomain, Addr}); +mk_addr_string(Strange) -> + lists:flatten(io_lib:format("~w", [Strange])). mk_addr_string_ntoa({_, _, _, _} = IP) -> diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl index 0a50174adc..17dfcd70b4 100644 --- a/lib/snmp/src/misc/snmp_config.erl +++ b/lib/snmp/src/misc/snmp_config.erl @@ -1676,7 +1676,9 @@ write_agent_snmp_conf(Dir, AgentIP, AgentUDP, EngineID, MMS) {intAgentIpAddress, AgentIP}, {snmpEngineID, EngineID}, {snmpEngineMaxMessageSize, MMS}], - do_write_agent_snmp_conf(Dir, Conf). + do_write_agent_snmp_conf(Dir, Conf); +write_agent_snmp_conf(_Dir, Domain, AgentAddr, _EngineID, _MMS) -> + error({bad_address, {Domain, AgentAddr}}). do_write_agent_snmp_conf(Dir, Conf) -> Comment = @@ -2153,7 +2155,9 @@ write_manager_snmp_conf(Dir, Domain_or_IP, Addr_or_Port, MMS, EngineID) -> {address, IP}]; _ when is_integer(Addr_or_Port) -> [{port, Addr_or_Port}, - {address, Domain_or_IP}] + {address, Domain_or_IP}]; + _ -> + error({bad_address, {Domain_or_IP, Addr_or_Port}}) end ++ [{engine_id, EngineID}, {max_message_size, MMS}], diff --git a/lib/snmp/test/snmp_manager_config_test.erl b/lib/snmp/test/snmp_manager_config_test.erl index 2f5c68d14d..f37e957dae 100644 --- a/lib/snmp/test/snmp_manager_config_test.erl +++ b/lib/snmp/test/snmp_manager_config_test.erl @@ -1048,7 +1048,7 @@ start_with_invalid_agents_conf_file1(Conf) when is_list(Conf) -> case config_start(Opts) of {error, Reason51} -> p("start failed (as expected): ~p", [Reason51]), - ?line {failed_check, _, _, _, {bad_address, _}} = Reason51, + ?line {failed_check, _, _, _, {bad_domain, _}} = Reason51, await_config_not_running(); OK_51 -> exit({error, {unexpected_success, "51", OK_51}}) -- cgit v1.2.3 From cc9fbe12c3e7c0c99462d72fe99ee9f29051353a Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Fri, 22 Aug 2014 12:12:29 +0200 Subject: Merge manager net_if_mt into net_if --- lib/snmp/src/manager/depend.mk | 5 +- lib/snmp/src/manager/snmpm_net_if.erl | 237 +++++- lib/snmp/src/manager/snmpm_net_if_mt.erl | 1340 +----------------------------- 3 files changed, 201 insertions(+), 1381 deletions(-) diff --git a/lib/snmp/src/manager/depend.mk b/lib/snmp/src/manager/depend.mk index 2e7783c8ed..60f61b0d3b 100644 --- a/lib/snmp/src/manager/depend.mk +++ b/lib/snmp/src/manager/depend.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2012. All Rights Reserved. +# Copyright Ericsson AB 2004-2014. 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 @@ -50,10 +50,11 @@ $(EBIN)/snmpm_net_if.$(EMULATOR): \ snmpm_network_interface.erl $(EBIN)/snmpm_net_if_mt.$(EMULATOR): \ + snmpm_net_if_mt.erl \ ../../include/snmp_types.hrl \ ../misc/snmp_debug.hrl \ ../misc/snmp_verbosity.hrl \ - snmpm_net_if_mt.erl \ + snmpm_net_if.erl \ snmpm_network_interface.erl $(EBIN)/snmpm_server.$(EMULATOR): \ diff --git a/lib/snmp/src/manager/snmpm_net_if.erl b/lib/snmp/src/manager/snmpm_net_if.erl index bdde8a5623..cb72871177 100644 --- a/lib/snmp/src/manager/snmpm_net_if.erl +++ b/lib/snmp/src/manager/snmpm_net_if.erl @@ -17,7 +17,9 @@ %% %CopyrightEnd% %% +-ifndef(snmpm_net_if_mt). -module(snmpm_net_if). +-endif. -behaviour(gen_server). -behaviour(snmpm_network_interface). @@ -148,6 +150,64 @@ filter_reset(Pid) -> cast(Pid, filter_reset). +%%%------------------------------------------------------------------- +%%% Multi-thread manager +%%%------------------------------------------------------------------- + +-ifdef(snmpm_net_if_mt). + +%% This function is called through the macro below to +%% (in the not multithreaded case) avoid creating the +%% Failer/4 fun, and to avoid calling the Worker through a fun +%% (now it shall not be a fun, just a code snippet). + +worker(Worker, Failer, #state{log = Log} = State) -> + Verbosity = get(verbosity), + spawn_opt( + fun () -> + try + put(sname, mnifw), + put(verbosity, Verbosity), + NewState = + case do_reopen_log(Log) of + Log -> + State; + NewLog -> + State#state{log = NewLog} + end, + Worker(NewState) + of + Result -> + %% Winds up in handle_info {'DOWN', ...} + erlang:exit({net_if_worker, Result}) + catch + Class:Reason -> + %% Winds up in handle_info {'DOWN', ...} + erlang:exit( + {net_if_worker, Failer, + Class, Reason, erlang:get_stacktrace()}) + end + end, + [monitor]). +-define( + worker(S, Worker, Failer, State), + begin + worker( + fun (S) -> begin Worker end end, + begin Failer end, + (State)) + end). + +-else. + +-define( + worker(S, Worker, _Failer, State), + begin (S) = (State), begin Worker end end). + +-endif. + + + %%%------------------------------------------------------------------- %%% Callback functions from gen_server %%%------------------------------------------------------------------- @@ -168,6 +228,14 @@ init([Server, NoteStore]) -> {error, Reason} -> {stop, Reason} end. + +-ifdef(snmpm_net_if_mt). +%% This should really be protected, but it also needs to +%% be writable for the worker processes, so... +-define(inform_table_opts, [set, public, named_table, {keypos, 1}]). +-else. +-define(inform_table_opts, [set, protected, named_table, {keypos, 1}]). +-endif. do_init(Server, NoteStore) -> process_flag(trap_exit, true), @@ -177,8 +245,7 @@ do_init(Server, NoteStore) -> process_flag(priority, Prio), %% -- Create inform request table -- - ets:new(snmpm_inform_request_table, - [set, protected, named_table, {keypos, 1}]), + ets:new(snmpm_inform_request_table, ?inform_table_opts), %% -- Verbosity -- {ok, Verbosity} = snmpm_config:system_info(net_if_verbosity), @@ -189,6 +256,7 @@ do_init(Server, NoteStore) -> %% -- MPD -- {ok, Vsns} = snmpm_config:system_info(versions), MpdState = snmpm_mpd:init(Vsns), + ?vdebug("MpdState: ~w", [MpdState]), %% -- Module dependent options -- {ok, Opts} = snmpm_config:system_info(net_if_options), @@ -205,6 +273,7 @@ do_init(Server, NoteStore) -> %% -- Audit trail log --- {ok, ATL} = snmpm_config:system_info(audit_trail_log), Log = do_init_log(ATL), + ?vdebug("Log: ~w", [Log]), {ok, DomainAddresses} = snmpm_config:system_info(transports), ?vdebug("DomainAddresses: ~w",[DomainAddresses]), @@ -344,20 +413,65 @@ do_init_log(true) -> Name, File, SeqNoGen, Size, Repair, true) of {ok, Log} -> ?vdebug("log created: ~w", [Log]), - {Log, Type}; + {Name, Log, Type}; {error, Reason} -> throw({error, {failed_create_audit_log, Reason}}) end; _ -> case snmp_log:create(Name, File, Size, Repair, true) of {ok, Log} -> - {Log, Type}; + ?vdebug("log created: ~w", [Log]), + {Name, Log, Type}; {error, Reason} -> throw({error, {failed_create_audit_log, Reason}}) end end. - +-ifdef(snmpm_net_if_mt). +do_reopen_log(undefined) -> + undefined; +do_reopen_log({Name, Log, Type}) -> + case snmp_log:open(Name, Log) of + {ok, NewLog} -> + {Name, NewLog, Type}; + {error, Reason} -> + warning_msg( + "NetIf worker ~p failed to open ATL:~n" + " ~p", [self(), Reason]), + undefined + end. +-endif. + +%% Close log +do_close_log(undefined) -> + ok; +do_close_log({_Name, Log, _Type}) -> + (catch snmp_log:sync(Log)), + (catch snmp_log:close(Log)), + ok; +do_close_log(_) -> + ok. + +%% Log +logger(undefined, _Type, _Domain, _Addr) -> + fun(_) -> + ok + end; +logger({_Name, Log, Types}, Type, Domain, Addr) -> + case lists:member(Type, Types) of + true -> + AddrString = + iolist_to_binary(snmp_conf:mk_addr_string({Domain, Addr})), + fun(Msg) -> + snmp_log:log(Log, Msg, AddrString) + end; + false -> + fun(_) -> + ok + end + end. + + %%-------------------------------------------------------------------- %% Func: handle_call/3 %% Returns: {reply, Reply, State} | @@ -475,11 +589,42 @@ handle_info({disk_log, _Node, Log, Info}, State) -> State2 = handle_disk_log(Log, Info, State), {noreply, State2}; +handle_info({'DOWN', _, _, _, _} = Info, State) -> + handle_info_down(Info, State); + handle_info(Info, State) -> + handle_info_unknown(Info, State). + + +handle_info_unknown(Info, State) -> warning_msg("received unknown info: ~n~p", [Info]), {noreply, State}. +-ifdef(snmpm_net_if_mt). +handle_info_down( + {'DOWN', _MRef, process, _Pid, + {net_if_worker, _Result}}, + State) -> + ?vdebug("received DOWN message from net_if worker [~w]: " + "~n Result: ~p", [_Pid, _Result]), + {noreply, State}; +handle_info_down( + {'DOWN', _MRef, process, Pid, + {net_if_worker, Failer, Class, Reason, Stacktrace} = _ExitStatus}, + State) -> + ?vdebug("received DOWN message from net_if worker [~w]: " + "~n ExitStatus: ~p", [Pid, _ExitStatus]), + Failer(Pid, Class, Reason, Stacktrace), + {noreply, State}; +handle_info_down(Info, State) -> + handle_info_unknown(Info, State). +-else. +handle_info_down(Info, State) -> + handle_info_unknown(Info, State). +-endif. + + %%-------------------------------------------------------------------- %% Func: terminate/2 %% Purpose: Shutdown the server @@ -493,14 +638,6 @@ terminate(Reason, #state{log = Log, irgc = IrGcRef}) -> ok. -do_close_log({Log, _Type}) -> - (catch snmp_log:sync(Log)), - (catch snmp_log:close(Log)), - ok; -do_close_log(_) -> - ok. - - %%---------------------------------------------------------------------- %% Func: code_change/3 %% Purpose: Convert process state when code is changed @@ -519,7 +656,20 @@ code_change(_Vsn, State, _Extra) -> %%% Internal functions %%%------------------------------------------------------------------- -maybe_handle_recv_msg( +maybe_handle_recv_msg(Domain, Addr, Bytes, State) -> + ?worker( + S, maybe_handle_recv_msg_mt(Domain, Addr, Bytes, S), + fun (Pid, Class, Reason, Stacktrace) -> + warning_msg( + "Worker process (~p) terminated " + "while processing (incomming) message from %s:~n" + "~w:~w at ~p", + [Pid, snmp_conf:mk_addr_string({Domain, Addr}), + Class, Reason, Stacktrace]) + end, + State). + +maybe_handle_recv_msg_mt( Domain, Addr, Bytes, #state{filter = FilterMod, transports = Transports} = State) -> {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), @@ -669,6 +819,19 @@ handle_inform_request( end. handle_inform_response(Ref, Domain, Addr, State) -> + ?worker( + S, handle_inform_response_mt(Ref, Domain, Addr, S), + fun (Pid, Class, Reason, Stacktrace) -> + warning_msg( + "Worker process (~p) terminated " + "while processing (outgoing) inform response for %s:~n" + "~w:~w at ~p", + [Pid, snmp_conf:mk_addr_string({Domain, Addr}), + Class, Reason, Stacktrace]) + end, + State). + +handle_inform_response_mt(Ref, Domain, Addr, State) -> Key = {Ref, Domain, Addr}, case ets:lookup(snmpm_inform_request_table, Key) of [{Key, _, {Vsn, ACM, RePdu}}] -> @@ -737,18 +900,30 @@ irgc_stop(undefined) -> irgc_stop(Ref) -> (catch erlang:cancel_timer(Ref)). - -maybe_handle_send_pdu( +maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State) -> + ?worker( + S, maybe_handle_send_pdu_mt(Pdu, Vsn, MsgData, Domain, Addr, S), + fun (Pid, Class, Reason, Stacktrace) -> + warning_msg( + "Worker process (~p) terminated " + "while processing (outgoing) pdu for %s:~n" + "~w:~w at ~p", + [Pid, snmp_conf:mk_addr_string({Domain, Addr}), + Class, Reason, Stacktrace]) + end, + State). + +maybe_handle_send_pdu_mt( Pdu, Vsn, MsgData, Domain, Addr, #state{filter = FilterMod, transports = Transports} = State) -> {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), case (catch FilterMod:accept_send_pdu(Arg1, Arg2, pdu_type_of(Pdu))) of false -> - inc(netIfPduOutDrops), - ok; + inc(netIfPduOutDrops); _ -> handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State) - end. + end, + ok. handle_send_pdu( Pdu, Vsn, MsgData, Domain, Addr, @@ -766,8 +941,7 @@ handle_send_pdu( ?vlog("PDU not sent: " "~n PDU: ~p" "~n Reason: ~p", [Pdu, Reason]), - Pid ! {snmp_error, Pdu, Reason}, - ok + Pid ! {snmp_error, Pdu, Reason} end. @@ -1085,27 +1259,6 @@ t() -> A*1000000000+B*1000+(C div 1000). -%% ------------------------------------------------------------------- - -logger(undefined, _Type, _Domain, _Addr) -> - fun(_) -> - ok - end; -logger({Log, Types}, Type, Domain, Addr) -> - case lists:member(Type, Types) of - true -> - AddrString = - iolist_to_binary(snmp_conf:mk_addr_string({Domain, Addr})), - fun(Msg) -> - snmp_log:log(Log, Msg, AddrString) - end; - false -> - fun(_) -> - ok - end - end. - - %% ------------------------------------------------------------------- %% info_msg(F, A) -> diff --git a/lib/snmp/src/manager/snmpm_net_if_mt.erl b/lib/snmp/src/manager/snmpm_net_if_mt.erl index 8f2ed6d8cd..62f6023657 100644 --- a/lib/snmp/src/manager/snmpm_net_if_mt.erl +++ b/lib/snmp/src/manager/snmpm_net_if_mt.erl @@ -17,1341 +17,7 @@ %% %CopyrightEnd% %% --module(snmpm_net_if_mt). - --behaviour(gen_server). --behaviour(snmpm_network_interface). - - -%% Network Interface callback functions --export([ - start_link/2, - stop/1, - send_pdu/6, % Backward compatibility - send_pdu/7, % Partly backward compatibility - send_pdu/8, % Backward compatibility - - inform_response/4, - - note_store/2, - - info/1, - verbosity/2, - %% system_info_updated/2, - get_log_type/1, set_log_type/2, - filter_reset/1 - ]). - -%% gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - code_change/3, terminate/2]). - --define(SNMP_USE_V3, true). --include("snmp_types.hrl"). --include("snmpm_internal.hrl"). --include("snmpm_atl.hrl"). --include("snmp_debug.hrl"). - -%% -define(VMODULE,"NET_IF"). --include("snmp_verbosity.hrl"). - --record(state, - { - server, - note_store, - transports = [], - mpd_state, - log, - irb = auto, % auto | {user, integer()} - irgc, - filter - }). - --record(transport, - {socket, - domain = snmpUDPDomain}). - --define(DEFAULT_FILTER_MODULE, snmpm_net_if_filter). --define(DEFAULT_FILTER_OPTS, [{module, ?DEFAULT_FILTER_MODULE}]). - --ifdef(snmp_debug). --define(GS_START_LINK(Args), - gen_server:start_link(?MODULE, Args, [{debug,[trace]}])). --else. --define(GS_START_LINK(Args), - gen_server:start_link(?MODULE, Args, [])). --endif. - - --define(IRGC_TIMEOUT, timer:minutes(5)). - --define(ATL_SEQNO_INITIAL, 1). --define(ATL_SEQNO_MAX, 2147483647). - - -%%%------------------------------------------------------------------- -%%% API -%%%------------------------------------------------------------------- -start_link(Server, NoteStore) -> - ?d("start_link -> entry with" - "~n Server: ~p" - "~n NoteStore: ~p", [Server, NoteStore]), - Args = [Server, NoteStore], - ?GS_START_LINK(Args). - -stop(Pid) -> - call(Pid, stop). - -send_pdu(Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port) -> - send_pdu( - Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port, ?DEFAULT_EXTRA_INFO). - -send_pdu(Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port, ExtraInfo) - when is_record(Pdu, pdu) -> - ?d("send_pdu -> entry with~n" - " Pid: ~p~n" - " Pdu: ~p~n" - " Vsn: ~p~n" - " MsgData: ~p~n" - " Domain/IP: ~p~n" - " Addr/Port: ~p", - [Pid, Pdu, Vsn, MsgData, Domain_or_Ip, Addr_or_Port]), - {Domain, Addr} = address(Domain_or_Ip, Addr_or_Port), - cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo}). - -send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Ip, Port, ExtraInfo) -> - send_pdu(Pid, Pdu, Vsn, MsgData, Domain, {Ip, Port}, ExtraInfo). - -note_store(Pid, NoteStore) -> - call(Pid, {note_store, NoteStore}). - -inform_response(Pid, Ref, Domain_or_Ip, Addr_or_Port) -> - {Domain, Addr} = address(Domain_or_Ip, Addr_or_Port), - cast(Pid, {inform_response, Ref, Domain, Addr}). - -info(Pid) -> - call(Pid, info). - -verbosity(Pid, V) -> - call(Pid, {verbosity, V}). - -%% system_info_updated(Pid, What) -> -%% call(Pid, {system_info_updated, What}). - -get_log_type(Pid) -> - call(Pid, get_log_type). - -set_log_type(Pid, NewType) -> - call(Pid, {set_log_type, NewType}). - -filter_reset(Pid) -> - cast(Pid, filter_reset). - - -%%%------------------------------------------------------------------- -%%% Callback functions from gen_server -%%%------------------------------------------------------------------- - -%%-------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%%-------------------------------------------------------------------- -init([Server, NoteStore]) -> - ?d("init -> entry with" - "~n Server: ~p" - "~n NoteStore: ~p", [Server, NoteStore]), - try do_init(Server, NoteStore) - catch - {error, Reason} -> - {stop, Reason} - end. - -do_init(Server, NoteStore) -> - process_flag(trap_exit, true), - - %% -- Prio -- - {ok, Prio} = snmpm_config:system_info(prio), - process_flag(priority, Prio), - - %% -- Create inform request table -- - %% This should really be protected, but it also needs to - %% be writable for the worker processes, so... - ets:new(snmpm_inform_request_table, - [set, public, named_table, {keypos, 1}]), - - %% -- Verbosity -- - {ok, Verbosity} = snmpm_config:system_info(net_if_verbosity), - put(sname, mnif), - put(verbosity, Verbosity), - ?vlog("starting", []), - - %% -- MPD -- - {ok, Vsns} = snmpm_config:system_info(versions), - MpdState = snmpm_mpd:init(Vsns), - ?vdebug("MpdState: ~w", [MpdState]), - - %% -- Module dependent options -- - {ok, Opts} = snmpm_config:system_info(net_if_options), - - %% -- Inform response behaviour -- - {ok, IRB} = snmpm_config:system_info(net_if_irb), - IrGcRef = irgc_start(IRB), - - %% Flow control -- - FilterOpts = get_opt(Opts, filter, []), - FilterMod = create_filter(FilterOpts), - ?vdebug("FilterMod: ~w", [FilterMod]), - - %% -- Audit trail log --- - {ok, ATL} = snmpm_config:system_info(audit_trail_log), - Log = do_init_log(ATL), - ?vdebug("Log: ~w", [Log]), - - {ok, DomainAddresses} = snmpm_config:system_info(transports), - ?vdebug("DomainAddresses: ~w",[DomainAddresses]), - CommonSocketOpts = common_socket_opts(Opts), - BindTo = get_opt(Opts, bind_to, false), - case - [begin - {IpPort, SocketOpts} = - socket_params(Domain, Address, BindTo, CommonSocketOpts), - Socket = socket_open(IpPort, SocketOpts), - #transport{socket = Socket, domain = Domain} - end || {Domain, Address} <- DomainAddresses] - of - [] -> - ?vinfo("No transports configured: ~p", [DomainAddresses]), - throw({error, {no_transports,DomainAddresses}}); - Transports -> - %% -- Initiate counters --- - init_counters(), - - %% -- We are done --- - State = #state{ - server = Server, - note_store = NoteStore, - mpd_state = MpdState, - transports = Transports, - log = Log, - irb = IRB, - irgc = IrGcRef, - filter = FilterMod}, - ?vdebug("started", []), - {ok, State} - end. - -socket_open(IpPort, SocketOpts) -> - ?vtrace("socket_open -> entry with~n" - " IpPort: ~p~n" - " SocketOpts: ~p", [IpPort, SocketOpts]), - case gen_udp:open(IpPort, SocketOpts) of - {error, _} = Error -> - throw(Error); - {ok, Socket} -> - Socket - end. - -socket_params(Domain, {IpAddr, IpPort}, BindTo, CommonSocketOpts) -> - Family = snmp_conf:tdomain_to_family(Domain), - SocketOpts = - case Family of - inet6 -> - [Family, {ipv6_v6only, true} | CommonSocketOpts]; - Family -> - [Family | CommonSocketOpts] - end, - case Family of - inet -> - case init:get_argument(snmp_fd) of - {ok, [[FdStr]]} -> - Fd = list_to_integer(FdStr), - case BindTo of - true -> - {IpPort, [{ip, IpAddr}, {fd, Fd} | SocketOpts]}; - _ -> - {0, [{fd, Fd} | SocketOpts]} - end; - error -> - {IpPort, [{ip, IpAddr} | SocketOpts]} - end; - _ -> - case BindTo of - true -> - {IpPort, [{ip, IpAddr} | SocketOpts]}; - _ -> - {IpPort, SocketOpts} - end - end. - -common_socket_opts(Opts) -> - [binary - | case get_opt(Opts, sndbuf, default) of - default -> - []; - Sz -> - [{sndbuf, Sz}] - end ++ - case get_opt(Opts, recbuf, default) of - default -> - []; - Sz -> - [{sndbuf, Sz}] - end ++ - case get_opt(Opts, no_reuse, false) of - false -> - [{reuseaddr, true}]; - _ -> - [] - end]. - - -create_filter(Opts) when is_list(Opts) -> - case get_opt(Opts, module, ?DEFAULT_FILTER_MODULE) of - ?DEFAULT_FILTER_MODULE = Mod -> - Mod; - Module -> - snmpm_network_interface_filter:verify(Module), - Module - end; -create_filter(BadOpts) -> - throw({error, {bad_filter_opts, BadOpts}}). - - -%% ---------------------------------------------------------------------- -%% Audit Trail Logger -%% ---------------------------------------------------------------------- - -%% Open log -do_init_log(false) -> - ?vtrace("do_init_log(false) -> entry", []), - undefined; -do_init_log(true) -> - ?vtrace("do_init_log(true) -> entry", []), - {ok, Type} = snmpm_config:system_info(audit_trail_log_type), - {ok, Dir} = snmpm_config:system_info(audit_trail_log_dir), - {ok, Size} = snmpm_config:system_info(audit_trail_log_size), - {ok, Repair} = snmpm_config:system_info(audit_trail_log_repair), - Name = ?audit_trail_log_name, - File = filename:absname(?audit_trail_log_file, Dir), - case snmpm_config:system_info(audit_trail_log_seqno) of - {ok, true} -> - Initial = ?ATL_SEQNO_INITIAL, - Max = ?ATL_SEQNO_MAX, - Module = snmpm_config, - Function = increment_counter, - Args = [atl_seqno, Initial, Max], - SeqNoGen = {Module, Function, Args}, - case snmp_log:create( - Name, File, SeqNoGen, Size, Repair, true) of - {ok, Log} -> - ?vdebug("log created: ~w", [Log]), - {Name, Log, Type}; - {error, Reason} -> - throw({error, {failed_create_audit_log, Reason}}) - end; - _ -> - case snmp_log:create(Name, File, Size, Repair, true) of - {ok, Log} -> - ?vdebug("log created: ~w", [Log]), - {Name, Log, Type}; - {error, Reason} -> - throw({error, {failed_create_audit_log, Reason}}) - end - end. - - -%%-------------------------------------------------------------------- -%% Func: handle_call/3 -%% Returns: {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | (terminate/2 is called) -%% {stop, Reason, State} (terminate/2 is called) -%%-------------------------------------------------------------------- -handle_call({verbosity, Verbosity}, _From, State) -> - ?vlog("received verbosity request", []), - put(verbosity, Verbosity), - {reply, ok, State}; - -%% handle_call({system_info_updated, What}, _From, State) -> -%% ?vlog("received system_info_updated request with What = ~p", [What]), -%% {NewState, Reply} = handle_system_info_updated(State, What), -%% {reply, Reply, NewState}; - -handle_call(get_log_type, _From, State) -> - ?vlog("received get-log-type request", []), - Reply = (catch handle_get_log_type(State)), - {reply, Reply, State}; - -handle_call({set_log_type, NewType}, _From, State) -> - ?vlog("received set-log-type request with NewType = ~p", [NewType]), - {NewState, Reply} = (catch handle_set_log_type(State, NewType)), - {reply, Reply, NewState}; - -handle_call({note_store, Pid}, _From, State) -> - ?vlog("received new note_store: ~w", [Pid]), - {reply, ok, State#state{note_store = Pid}}; - -handle_call(stop, _From, State) -> - ?vlog("received stop request", []), - Reply = ok, - {stop, normal, Reply, State}; - -handle_call(info, _From, State) -> - ?vlog("received info request", []), - Reply = get_info(State), - {reply, Reply, State}; - -handle_call(Req, From, State) -> - warning_msg("received unknown request (from ~p): ~n~p", [Req, From]), - {reply, {error, {invalid_request, Req}}, State}. - - -%%-------------------------------------------------------------------- -%% Func: handle_cast/2 -%% Returns: {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} (terminate/2 is called) -%%-------------------------------------------------------------------- -handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo}, - State) -> - ?vlog("received send_pdu message with~n" - " Pdu: ~p~n" - " Vsn: ~p~n" - " MsgData: ~p~n" - " Domain: ~p~n" - " Addr: ~p", [Pdu, Vsn, MsgData, Domain, Addr]), - maybe_process_extra_info(ExtraInfo), - handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State), - {noreply, State}; - -handle_cast({inform_response, Ref, Domain, Addr}, State) -> - ?vlog("received inform_response message with~n" - " Ref: ~p~n" - " Domain: ~p~n" - " Addr: ~p", [Ref, Domain, Addr]), - handle_inform_response(Ref, Domain, Addr, State), - {noreply, State}; - -handle_cast(filter_reset, State) -> - ?vlog("received filter_reset message", []), - reset_counters(), - {noreply, State}; - -handle_cast(Msg, State) -> - warning_msg("received unknown message: ~n~p", [Msg]), - {noreply, State}. - - -%%-------------------------------------------------------------------- -%% Func: handle_info/2 -%% Returns: {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} (terminate/2 is called) -%%-------------------------------------------------------------------- -handle_info( - {udp, Socket, IpAddr, IpPort, Bytes}, - #state{transports = Transports} = State) -> - Size = byte_size(Bytes), - case lists:keyfind(Socket, #transport.socket, Transports) of - #transport{socket = Socket, domain = Domain} -> - ?vlog("received ~w bytes from ~p:~p [~w]", - [Size, IpAddr, IpPort, Socket]), - handle_udp(Domain, {IpAddr, IpPort}, Bytes, State), - {noreply, State}; - false -> - warning_msg("Received ~w bytes on unknown port: ~p from ~s", - [Size, Socket, format_address({IpAddr, IpPort})]), - {noreply, State} - end; - -handle_info(inform_response_gc, State) -> - ?vlog("received inform_response_gc message", []), - State2 = handle_inform_response_gc(State), - {noreply, State2}; - -handle_info({disk_log, _Node, Log, Info}, State) -> - ?vlog("received disk_log message: " - "~n Info: ~p", [Info]), - State2 = handle_disk_log(Log, Info, State), - {noreply, State2}; - -handle_info({'DOWN', _MRef, process, _Pid, {net_if_worker, _Result}}, - State) -> - ?vdebug("received DOWN message from net_if worker [~w]: " - "~n Result: ~p", [_Pid, _Result]), - {noreply, State}; -handle_info( - {'DOWN', _MRef, process, Pid, - {net_if_worker, Failer, Class, Reason, Stacktrace} = _ExitStatus}, - State) -> - ?vdebug("received DOWN message from net_if worker [~w]: " - "~n ExitStatus: ~p", [Pid, _ExitStatus]), - Failer(Pid, Class, Reason, Stacktrace), - {noreply, State}; - -handle_info(Info, State) -> - warning_msg("received unknown info: ~n~p", [Info]), - {noreply, State}. - - -%%-------------------------------------------------------------------- -%% Func: terminate/2 -%% Purpose: Shutdown the server -%% Returns: any (ignored by gen_server) -%%-------------------------------------------------------------------- -terminate(Reason, #state{log = Log, irgc = IrGcRef}) -> - ?vdebug("terminate: ~p", [Reason]), - irgc_stop(IrGcRef), - %% Close logs - do_close_log(Log), - ok. - - -do_close_log({_Name, Log, _Type}) -> - (catch snmp_log:sync(Log)), - (catch snmp_log:close(Log)), - ok; -do_close_log(_) -> - ok. - - -%%---------------------------------------------------------------------- -%% Func: code_change/3 -%% Purpose: Convert process state when code is changed -%% Returns: {ok, NewState} -%%---------------------------------------------------------------------- - -code_change(_Vsn, State, _Extra) -> - ?d("code_change -> entry with" - "~n Vsn: ~p" - "~n State: ~p" - "~n Extra: ~p", [_Vsn, State, _Extra]), - {ok, State}. - - -%%%------------------------------------------------------------------- -%%% Internal functions -%%%------------------------------------------------------------------- - -handle_udp(Domain, Addr, Bytes, State) -> - worker( - fun (S) -> - maybe_handle_recv_msg(Domain, Addr, Bytes, S) - end, - fun (Pid, Class, Reason, Stacktrace) -> - warning_msg( - "Worker process (~p) terminated " - "while processing (incomming) message from %s:~n" - "~w:~w at ~p", - [Pid, snmp_conf:mk_addr_string({Domain, Addr}), - Class, Reason, Stacktrace]) - end, - State). - -maybe_handle_recv_msg( - Domain, Addr, Bytes, - #state{filter = FilterMod, transports = Transports} = State) -> - {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), - case (catch FilterMod:accept_recv(Arg1, Arg2)) of - false -> - %% Drop the received packet - inc(netIfMsgInDrops); - _ -> - handle_recv_msg(Domain, Addr, Bytes, State) - end, - ok. - - -handle_recv_msg(Domain, Addr, Bytes, #state{server = Pid}) - when is_binary(Bytes) andalso (size(Bytes) =:= 0) -> - Pid ! {snmp_error, {empty_message, Domain, Addr}, Domain, Addr}; -%% -handle_recv_msg( - Domain, Addr, Bytes, - #state{ - server = Pid, - note_store = NoteStore, - mpd_state = MpdState, - log = Log} = State) -> - Logger = logger(Log, read, Domain, Addr), - case (catch snmpm_mpd:process_msg( - Bytes, Domain, Addr, MpdState, NoteStore, Logger)) of - - {ok, Vsn, Pdu, MS, ACM} -> - maybe_handle_recv_pdu( - Domain, Addr, Vsn, Pdu, MS, ACM, Logger, State); - - {discarded, Reason, Report} -> - ?vdebug("discarded: ~p", [Reason]), - ErrorInfo = {failed_processing_message, Reason}, - Pid ! {snmp_error, ErrorInfo, Domain, Addr}, - maybe_udp_send(Domain, Addr, Report, State); - {discarded, Reason} -> - ?vdebug("discarded: ~p", [Reason]), - ErrorInfo = {failed_processing_message, Reason}, - Pid ! {snmp_error, ErrorInfo, Domain, Addr}; - - Error -> - error_msg("processing of received message failed: " - "~n ~p", [Error]) - end. - - -maybe_handle_recv_pdu( - Domain, Addr, Vsn, #pdu{type = Type} = Pdu, PduMS, ACM, Logger, - #state{filter = FilterMod, transports = Transports} = State) -> - {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), - case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, Type)) of - false -> - inc(netIfPduInDrops); - _ -> - handle_recv_pdu( - Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State) - end; -maybe_handle_recv_pdu( - Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, - #state{filter = FilterMod, transports = Transports} = State) - when is_record(Trap, trappdu) -> - {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), - case (catch FilterMod:accept_recv_pdu(Arg1, Arg2, trappdu)) of - false -> - inc(netIfPduInDrops); - _ -> - handle_recv_pdu( - Domain, Addr, Vsn, Trap, PduMS, ACM, Logger, State) - end; -maybe_handle_recv_pdu( - Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State) -> - handle_recv_pdu(Domain, Addr, Vsn, Pdu, PduMS, ACM, Logger, State). - - -handle_recv_pdu( - Domain, Addr, Vsn, - #pdu{type = 'inform-request'} = Pdu, _PduMS, ACM, Logger, - #state{server = Pid, irb = IRB} = State) -> - handle_inform_request( - IRB, Pid, Vsn, Pdu, ACM, Domain, Addr, Logger, State); -handle_recv_pdu( - Domain, Addr, _Vsn, - #pdu{type = report} = Pdu, _PduMS, ok, _Logger, - #state{server = Pid} = _State) -> - ?vtrace("received report - ok", []), - Pid ! {snmp_report, {ok, Pdu}, Domain, Addr}; -handle_recv_pdu( - Domain, Addr, _Vsn, - #pdu{type = report} = Pdu, _PduMS, {error, ReqId, Reason}, _Logger, - #state{server = Pid} = _State) -> - ?vtrace("received report - error", []), - Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Domain, Addr}; -handle_recv_pdu( - Domain, Addr, _Vsn, - #pdu{type = 'snmpv2-trap'} = Pdu, _PduMS, _ACM, _Logger, - #state{server = Pid} = _State) -> - ?vtrace("received snmpv2-trap", []), - Pid ! {snmp_trap, Pdu, Domain, Addr}; -handle_recv_pdu( - Domain, Addr, _Vsn, Trap, _PduMS, _ACM, _Logger, - #state{server = Pid} = _State) when is_record(Trap, trappdu) -> - ?vtrace("received trappdu", []), - Pid ! {snmp_trap, Trap, Domain, Addr}; -handle_recv_pdu( - Domain, Addr, _Vsn, Pdu, _PduMS, _ACM, _Logger, - #state{server = Pid} = _State) when is_record(Pdu, pdu) -> - ?vtrace("received pdu", []), - Pid ! {snmp_pdu, Pdu, Domain, Addr}; -handle_recv_pdu( - _Domain, _Addr, _Vsn, Pdu, _PduMS, ACM, _Logger, _State) -> - ?vlog("received unexpected pdu: " - "~n Pdu: ~p" - "~n ACM: ~p", [Pdu, ACM]). - - -handle_inform_request( - auto, Pid, Vsn, Pdu, ACM, Domain, Addr, Logger, State) -> - ?vtrace("received inform-request (true)", []), - Pid ! {snmp_inform, ignore, Pdu, Domain, Addr}, - RePdu = make_response_pdu(Pdu), - maybe_send_inform_response(RePdu, Vsn, ACM, Domain, Addr, Logger, State); -handle_inform_request( - {user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu, - ACM, Domain, Addr, _Logger, _State) -> - ?vtrace("received inform-request (false)", []), - - Pid ! {snmp_inform, ReqId, Pdu, Domain, Addr}, - - %% Before we go any further, we need to check that we have not - %% already received this message (possible resend). - - Key = {ReqId, Domain, Addr}, - case ets:lookup(snmpm_inform_request_table, Key) of - [_] -> - %% OK, we already know about this. We assume this - %% is a resend. Either the agent is really eager or - %% the user has not answered yet. Bad user! - ok; - [] -> - RePdu = make_response_pdu(Pdu), - Expire = t() + To, - Rec = {Key, Expire, {Vsn, ACM, RePdu}}, - ets:insert(snmpm_inform_request_table, Rec) - end. - -handle_inform_response(Ref, Domain, Addr, State) -> - worker( - fun (S) -> - do_handle_inform_response(Ref, Domain, Addr, S) - end, - fun (Pid, Class, Reason, Stacktrace) -> - warning_msg( - "Worker process (~p) terminated " - "while processing (outgoing) inform response for %s:~n" - "~w:~w at ~p", - [Pid, snmp_conf:mk_addr_string({Domain, Addr}), - Class, Reason, Stacktrace]) - end, - State). - -do_handle_inform_response(Ref, Domain, Addr, State) -> - Key = {Ref, Domain, Addr}, - case ets:lookup(snmpm_inform_request_table, Key) of - [{Key, _, {Vsn, ACM, RePdu}}] -> - Logger = logger(State#state.log, read, Domain, Addr), - ets:delete(snmpm_inform_request_table, Key), - maybe_send_inform_response( - RePdu, Vsn, ACM, Domain, Addr, Logger, State); - [] -> - %% Already acknowledged, or the user was to slow to reply... - ok - end, - ok. - -maybe_send_inform_response( - RePdu, Vsn, ACM, Domain, Addr, Logger, - #state{ - server = Pid, - filter = FilterMod, - transports = Transports} = State) -> - {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), - case (catch FilterMod:accept_send_pdu( - Arg1, Arg2, pdu_type_of(RePdu))) - of - false -> - inc(netIfPduOutDrops), - ok; - _ -> - case snmpm_mpd:generate_response_msg(Vsn, RePdu, ACM, Logger) of - {ok, Msg} -> - maybe_udp_send(Domain, Addr, Msg, State); - {discarded, Reason} -> - ?vlog("failed generating response message:" - "~n Reason: ~p", [Reason]), - ReqId = RePdu#pdu.request_id, - ErrorInfo = {failed_generating_response, {RePdu, Reason}}, - Pid ! {snmp_error, ReqId, ErrorInfo, Domain, Addr} - end - end. - -handle_inform_response_gc(#state{irb = IRB} = State) -> - ets:safe_fixtable(snmpm_inform_request_table, true), - do_irgc(ets:first(snmpm_inform_request_table), t()), - ets:safe_fixtable(snmpm_inform_request_table, false), - State#state{irgc = irgc_start(IRB)}. - -%% We are deleting at the same time as we are traversing the table!!! -do_irgc('$end_of_table', _) -> - ok; -do_irgc(Key, Now) -> - Next = ets:next(snmpm_inform_request_table, Key), - case ets:lookup(snmpm_inform_request_table, Key) of - [{Key, BestBefore, _}] when BestBefore < Now -> - ets:delete(snmpm_inform_request_table, Key); - _ -> - ok - end, - do_irgc(Next, Now). - -irgc_start(auto) -> - undefined; -irgc_start(_) -> - erlang:send_after(?IRGC_TIMEOUT, self(), inform_response_gc). - -irgc_stop(undefined) -> - ok; -irgc_stop(Ref) -> - (catch erlang:cancel_timer(Ref)). - - -handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State) -> - worker( - fun (S) -> - maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, S) - end, - fun (Pid, Class, Reason, Stacktrace) -> - warning_msg( - "Worker process (~p) terminated " - "while processing (outgoing) pdu for %s:~n" - "~w:~w at ~p", - [Pid, snmp_conf:mk_addr_string({Domain, Addr}), - Class, Reason, Stacktrace]) - end, - State). - -maybe_handle_send_pdu( - Pdu, Vsn, MsgData, Domain, Addr, - #state{filter = FilterMod, transports = Transports} = State) -> - {Arg1, Arg2} = fix_filter_address(Transports, {Domain, Addr}), - case (catch FilterMod:accept_send_pdu(Arg1, Arg2, pdu_type_of(Pdu))) of - false -> - inc(netIfPduOutDrops), - ok; - _ -> - do_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, State) - end. - -do_handle_send_pdu( - Pdu, Vsn, MsgData, Domain, Addr, - #state{ - server = Pid, - note_store = NoteStore, - log = Log} = State) -> - Logger = logger(Log, write, Domain, Addr), - case (catch snmpm_mpd:generate_msg( - Vsn, NoteStore, Pdu, MsgData, Logger)) of - {ok, Msg} -> - ?vtrace("do_handle_send_pdu -> message generated", []), - maybe_udp_send(Domain, Addr, Msg, State); - {discarded, Reason} -> - ?vlog("PDU not sent: " - "~n PDU: ~p" - "~n Reason: ~p", [Pdu, Reason]), - Pid ! {snmp_error, Pdu, Reason}, - ok - end. - - -maybe_udp_send( - Domain, Addr, Msg, - #state{filter = FilterMod, transports = Transports}) -> - To = {Domain, Addr}, - {Arg1, Arg2} = fix_filter_address(Transports, To), - case (catch FilterMod:accept_send(Arg1, Arg2)) of - false -> - inc(netIfMsgOutDrops), - ok; - _ -> - case select_transport_from_domain(Domain, Transports) of - false -> - error_msg( - "Can not find transport~n" - " size: ~p~n" - " to: ~s", - [sz(Msg), format_address(To)]); - #transport{socket = Socket} -> - udp_send(Socket, Addr, Msg) - end - end. - -udp_send(Sock, To, Msg) -> - {IpAddr, IpPort} = - case To of - {Domain, Addr} when is_atom(Domain) -> - Addr; - {_, P} = Addr when is_integer(P) -> - Addr - end, - try gen_udp:send(Sock, IpAddr, IpPort, Msg) of - ok -> - ?vdebug("sent ~w bytes to ~w:~w [~w]", - [sz(Msg), IpAddr, IpPort, Sock]), - ok; - {error, Reason} -> - error_msg("failed sending message to ~p:~p:~n" - " ~p",[IpAddr, IpPort, Reason]) - catch - error:Error -> - error_msg("failed sending message to ~p:~p:~n" - " error:~p~n" - " ~p", - [IpAddr, IpPort, Error, erlang:get_stacktrace()]) - end. - -sz(B) when is_binary(B) -> - byte_size(B); -sz(L) when is_list(L) -> - length(L); -sz(_) -> - undefined. - - -handle_disk_log(_Log, {wrap, NoLostItems}, State) -> - ?vlog("Audit Trail Log - wrapped: ~w previously logged items where lost", - [NoLostItems]), - State; -handle_disk_log(_Log, {truncated, NoLostItems}, State) -> - ?vlog("Audit Trail Log - truncated: ~w items where lost when truncating", - [NoLostItems]), - State; -handle_disk_log(_Log, full, State) -> - error_msg("Failed to write to Audit Trail Log (full)", []), - State; -handle_disk_log(_Log, {error_status, ok}, State) -> - State; -handle_disk_log(_Log, {error_status, {error, Reason}}, State) -> - error_msg("Error status received from Audit Trail Log: " - "~n~p", [Reason]), - State; -handle_disk_log(_Log, _Info, State) -> - State. - - -%% mk_discovery_msg('version-3', Pdu, _VsnHdr, UserName) -> -%% ScopedPDU = #scopedPdu{contextEngineID = "", -%% contextName = "", -%% data = Pdu}, -%% Bytes = snmp_pdus:enc_scoped_pdu(ScopedPDU), -%% MsgID = get(msg_id), -%% put(msg_id,MsgID+1), -%% UsmSecParams = -%% #usmSecurityParameters{msgAuthoritativeEngineID = "", -%% msgAuthoritativeEngineBoots = 0, -%% msgAuthoritativeEngineTime = 0, -%% msgUserName = UserName, -%% msgPrivacyParameters = "", -%% msgAuthenticationParameters = ""}, -%% SecBytes = snmp_pdus:enc_usm_security_parameters(UsmSecParams), -%% PduType = Pdu#pdu.type, -%% Hdr = #v3_hdr{msgID = MsgID, -%% msgMaxSize = 1000, -%% msgFlags = snmp_misc:mk_msg_flags(PduType, 0), -%% msgSecurityModel = ?SEC_USM, -%% msgSecurityParameters = SecBytes}, -%% Msg = #message{version = 'version-3', vsn_hdr = Hdr, data = Bytes}, -%% case (catch snmp_pdus:enc_message_only(Msg)) of -%% {'EXIT', Reason} -> -%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), -%% error; -%% L when list(L) -> -%% {Msg, L} -%% end; -%% mk_discovery_msg(Version, Pdu, {Com, _, _, _, _}, UserName) -> -%% Msg = #message{version = Version, vsn_hdr = Com, data = Pdu}, -%% case catch snmp_pdus:enc_message(Msg) of -%% {'EXIT', Reason} -> -%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), -%% error; -%% L when list(L) -> -%% {Msg, L} -%% end. - - -%% mk_msg('version-3', Pdu, {Context, User, EngineID, CtxEngineId, SecLevel}, -%% MsgData) -> -%% %% Code copied from snmp_mpd.erl -%% {MsgId, SecName, SecData} = -%% if -%% tuple(MsgData), Pdu#pdu.type == 'get-response' -> -%% MsgData; -%% true -> -%% Md = get(msg_id), -%% put(msg_id, Md + 1), -%% {Md, User, []} -%% end, -%% ScopedPDU = #scopedPdu{contextEngineID = CtxEngineId, -%% contextName = Context, -%% data = Pdu}, -%% ScopedPDUBytes = snmp_pdus:enc_scoped_pdu(ScopedPDU), - -%% PduType = Pdu#pdu.type, -%% V3Hdr = #v3_hdr{msgID = MsgId, -%% msgMaxSize = 1000, -%% msgFlags = snmp_misc:mk_msg_flags(PduType, SecLevel), -%% msgSecurityModel = ?SEC_USM}, -%% Message = #message{version = 'version-3', vsn_hdr = V3Hdr, -%% data = ScopedPDUBytes}, -%% SecEngineID = case PduType of -%% 'get-response' -> snmp_framework_mib:get_engine_id(); -%% _ -> EngineID -%% end, -%% case catch snmp_usm:generate_outgoing_msg(Message, SecEngineID, -%% SecName, SecData, SecLevel) of -%% {'EXIT', Reason} -> -%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), -%% error; -%% {error, Reason} -> -%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), -%% error; -%% Packet -> -%% Packet -%% end; -%% mk_msg(Version, Pdu, {Com, _User, _EngineID, _Ctx, _SecLevel}, _SecData) -> -%% Msg = #message{version = Version, vsn_hdr = Com, data = Pdu}, -%% case catch snmp_pdus:enc_message(Msg) of -%% {'EXIT', Reason} -> -%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), -%% error; -%% B when list(B) -> -%% B -%% end. - - -%% handle_system_info_updated(#state{log = {Log, _OldType}} = State, -%% audit_trail_log_type = _What) -> -%% %% Just to make sure, check that ATL is actually enabled -%% case snmpm_config:system_info(audit_trail_log) of -%% {ok, true} -> -%% {ok, Type} = snmpm_config:system_info(audit_trail_log_type), -%% NewState = State#state{log = {Log, Type}}, -%% {NewState, ok}; -%% _ -> -%% {State, {error, {adt_not_enabled}}} -%% end; -%% handle_system_info_updated(_State, _What) -> -%% ok. - -handle_get_log_type(#state{log = {_Log, Value}} = State) -> - %% Just to make sure, check that ATL is actually enabled - case snmpm_config:system_info(audit_trail_log) of - {ok, true} -> - Type = - case {lists:member(read, Value), lists:member(write, Value)} of - {true, true} -> - read_write; - {true, false} -> - read; - {false, true} -> - write; - {false, false} -> - throw({State, {error, {bad_atl_type, Value}}}) - end, - {ok, Type}; - _ -> - {error, not_enabled} - end; -handle_get_log_type(_State) -> - {error, not_enabled}. - -handle_set_log_type(#state{log = {Log, OldValue}} = State, NewType) -> - %% Just to make sure, check that ATL is actually enabled - case snmpm_config:system_info(audit_trail_log) of - {ok, true} -> - NewValue = - case NewType of - read -> - [read]; - write -> - [write]; - read_write -> - [read,write]; - _ -> - throw({State, {error, {bad_atl_type, NewType}}}) - end, - NewState = State#state{log = {Log, NewValue}}, - OldType = - case {lists:member(read, OldValue), - lists:member(write, OldValue)} of - {true, true} -> - read_write; - {true, false} -> - read; - {false, true} -> - write; - {false, false} -> - throw({State, {error, {bad_atl_type, OldValue}}}) - end, - {NewState, {ok, OldType}}; - _ -> - {State, {error, not_enabled}} - end; -handle_set_log_type(State, _NewType) -> - {State, {error, not_enabled}}. - - -select_transport_from_domain(Domain, Transports) when is_atom(Domain) -> - Pos = #transport.domain, - case lists:keyfind(Domain, Pos, Transports) of - #transport{domain = Domain} = Transport -> - Transport; - false when Domain == snmpUDPDomain -> - lists:keyfind(transportDomainUdpIpv4, Pos, Transports); - false when Domain == transportDomainUdpIpv4 -> - lists:keyfind(snmpUDPDomain, Pos, Transports); - false -> - false - end. - -%% If the manager uses legacy snmpUDPDomain e.g has not set -%% {domain, _}, then make sure snmpm_network_interface_filter -%% gets legacy arguments to not break backwards compatibility. -%% -fix_filter_address(Transports, Address) -> - DefaultDomain = snmpm_config:default_transport_domain(), - case Transports of - [#transport{domain = DefaultDomain}, DefaultDomain] -> - case Address of - {Domain, Addr} when is_atom(Domain) -> - Addr; - {_, IpPort} = Addr when is_integer(IpPort) -> - Addr - end; - _ -> - Address - end. - -address(Domain, Addr) when is_atom(Domain) -> - {Domain, Addr}; -address(Ip, Port) when is_integer(Port) -> - {snmpm_config:default_transport_domain(), {Ip, Port}}. - -format_address(Address) -> - iolist_to_binary(snmp_conf:mk_addr_string(Address)). - -%% ------------------------------------------------------------------- - -worker(Worker, Failer, State) -> - Verbosity = get(verbosity), - spawn_opt( - fun () -> - try - put(sname, mnifw), - put(verbosity, Verbosity), - Worker(worker_init(State)) - of - Result -> - %% Winds up in handle_info {'DOWN', ...} - erlang:exit({net_if_worker, Result}) - catch - Class:Reason -> - %% Winds up in handle_info {'DOWN', ...} - erlang:exit( - {net_if_worker, Failer, - Class, Reason, erlang:get_stacktrace()}) - end - end, - [monitor]). - -worker_init(#state{log = undefined} = State) -> - State; -worker_init(#state{log = {Name, Log, Type}} = State) -> - case snmp_log:open(Name, Log) of - {ok, NewLog} -> - State#state{log = {Name, NewLog, Type}}; - {error, Reason} -> - warning_msg("NetIf worker ~p failed opening ATL: " - "~n ~p", [self(), Reason]), - State#state{log = {Name, undefined, Type}} - end; -worker_init(State) -> - ?vinfo("worker_init -> entry with invalid data: " - "~n State: ~p", [State]), - erlang:error({worker_init, State}). - -%% ------------------------------------------------------------------- - -make_response_pdu(#pdu{request_id = ReqId, varbinds = Vbs}) -> - #pdu{type = 'get-response', - request_id = ReqId, - error_status = noError, - error_index = 0, - varbinds = Vbs}. - - -%% ---------------------------------------------------------------- - -pdu_type_of(#pdu{type = Type}) -> - Type; -pdu_type_of(TrapPdu) when is_record(TrapPdu, trappdu) -> - trap. - - -%% ------------------------------------------------------------------- - -%% At this point this function is used during testing -maybe_process_extra_info(?DEFAULT_EXTRA_INFO) -> - ok; -maybe_process_extra_info({?SNMPM_EXTRA_INFO_TAG, Fun}) - when is_function(Fun, 0) -> - (catch Fun()), - ok; -maybe_process_extra_info(_ExtraInfo) -> - ok. - - -%% ------------------------------------------------------------------- - -t() -> - {A,B,C} = erlang:now(), - A*1000000000+B*1000+(C div 1000). - - -%% ------------------------------------------------------------------- - -logger(undefined, _Type, _Domain, _Addr) -> - fun(_) -> - ok - end; -logger({_Name, Log, Types}, Type, Domain, Addr) -> - case lists:member(Type, Types) of - true -> - AddrString = - iolist_to_binary(snmp_conf:mk_addr_string({Domain, Addr})), - fun(Msg) -> - snmp_log:log(Log, Msg, AddrString) - end; - false -> - fun(_) -> - ok - end - end. - - -%% ------------------------------------------------------------------- - -%% info_msg(F, A) -> -%% ?snmpm_info("NET-IF server: " ++ F, A). - -warning_msg(F, A) -> - ?snmpm_warning("NET-IF server: " ++ F, A). - -error_msg(F, A) -> - ?snmpm_error("NET-IF server: " ++ F, A). - - - -%%%------------------------------------------------------------------- - -% get_opt(Key, Opts) -> -% ?vtrace("get option ~w", [Key]), -% snmp_misc:get_option(Key, Opts). - -get_opt(Opts, Key, Def) -> - ?vtrace("get option ~w with default ~p", [Key, Def]), - snmp_misc:get_option(Key, Opts, Def). - - -%% ------------------------------------------------------------------- - -get_info(#state{transports = Transports}) -> - ProcSize = proc_mem(self()), - [{process_memory, ProcSize} - | [{port_info, get_port_info(Socket)} - || #transport{socket = Socket} <- Transports]]. - -proc_mem(P) when is_pid(P) -> - case (catch erlang:process_info(P, memory)) of - {memory, Sz} when is_integer(Sz) -> - Sz; - _ -> - undefined - end. -%% proc_mem(_) -> -%% undefined. - - -get_port_info(Id) -> - PortInfo = - case (catch erlang:port_info(Id)) of - PI when is_list(PI) -> - [{port_info, PI}]; - _ -> - [] - end, - PortStatus = - case (catch prim_inet:getstatus(Id)) of - {ok, PS} -> - [{port_status, PS}]; - _ -> - [] - end, - PortAct = - case (catch inet:getopts(Id, [active])) of - {ok, PA} -> - [{port_act, PA}]; - _ -> - [] - end, - PortStats = - case (catch inet:getstat(Id)) of - {ok, Stat} -> - [{port_stats, Stat}]; - _ -> - [] - end, - IfList = - case (catch inet:getif(Id)) of - {ok, IFs} -> - [{interfaces, IFs}]; - _ -> - [] - end, - BufSz = - case (catch inet:getopts(Id, [recbuf, sndbuf, buffer])) of - {ok, Sz} -> - [{buffer_size, Sz}]; - _ -> - [] - end, - [{socket, Id}] ++ - IfList ++ - PortStats ++ - PortInfo ++ - PortStatus ++ - PortAct ++ - BufSz. - - -%%----------------------------------------------------------------- -%% Counter functions -%%----------------------------------------------------------------- -init_counters() -> - F = fun(Counter) -> maybe_create_counter(Counter) end, - lists:map(F, counters()). - -reset_counters() -> - F = fun(Counter) -> snmpm_config:reset_stats_counter(Counter) end, - lists:map(F, counters()). - -maybe_create_counter(Counter) -> - snmpm_config:maybe_cre_stats_counter(Counter, 0). - -counters() -> - [ - netIfMsgOutDrops, - netIfMsgInDrops, - netIfPduOutDrops, - netIfPduInDrops - ]. - -inc(Name) -> inc(Name, 1). -inc(Name, N) -> snmpm_config:incr_stats_counter(Name, N). - -%% get_counters() -> -%% Counters = counters(), -%% get_counters(Counters, []). - -%% get_counters([], Acc) -> -%% lists:reverse(Acc); -%% get_counters([Counter|Counters], Acc) -> -%% case snmpm_config:get_stats_counter(Counter) of -%% {ok, CounterVal} -> -%% get_counters(Counters, [{Counter, CounterVal}|Acc]); -%% _ -> -%% get_counters(Counters, Acc) -%% end. - - -%% ---------------------------------------------------------------- - -call(Pid, Req) -> - call(Pid, Req, infinity). - -call(Pid, Req, Timeout) -> - gen_server:call(Pid, Req, Timeout). - -cast(Pid, Msg) -> - gen_server:cast(Pid, Msg). +-define(snmpm_net_if_mt, true). +-module(snmpm_net_if_mt). +-include("snmpm_net_if.erl"). -- cgit v1.2.3 From 46f752b15205977cb1191c1693e942a499d351f9 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Mon, 25 Aug 2014 10:59:54 +0200 Subject: Raise timeout and see if testcases stabilize --- lib/snmp/test/snmp_to_snmpnet_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl index c514eafd7d..2f96493ac5 100644 --- a/lib/snmp/test/snmp_to_snmpnet_SUITE.erl +++ b/lib/snmp/test/snmp_to_snmpnet_SUITE.erl @@ -170,7 +170,7 @@ end_per_group(_GroupName, Config) -> Config. init_per_testcase(_Case, Config) -> - Dog = ct:timetrap(10000), + Dog = ct:timetrap(20000), application:stop(snmp), application:unload(snmp), [{watchdog, Dog} | Config]. -- cgit v1.2.3 From 5bd1edc7b53dbcea6f63e0a7fb57925935e6b293 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Fri, 29 Aug 2014 11:19:52 +0200 Subject: Clean up some config warts --- lib/snmp/src/agent/snmp_framework_mib.erl | 34 ++++++++++++++----------- lib/snmp/src/agent/snmp_target_mib.erl | 33 +++++++++++++++--------- lib/snmp/src/agent/snmpa_conf.erl | 15 ++++++++++- lib/snmp/src/manager/snmpm_conf.erl | 7 +++--- lib/snmp/src/manager/snmpm_config.erl | 42 +++++++++++++++++++++++++------ lib/snmp/src/manager/snmpm_server.erl | 11 +++++++- 6 files changed, 103 insertions(+), 39 deletions(-) diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl index 9d3f7ef5e7..6ff9224d34 100644 --- a/lib/snmp/src/agent/snmp_framework_mib.erl +++ b/lib/snmp/src/agent/snmp_framework_mib.erl @@ -207,22 +207,28 @@ check_agent({intAgentIpAddress = Tag, Ip} = Entry, {Domain, Port} = State) -> [{Tag, FixedIp}, {intAgentTransports, [{Domain, {FixedIp, Port}}]}] end, State}; -check_agent({intAgentTransports = Tag, Transports}, {_, Port} = State) -> +check_agent({intAgentTransports = Tag, Transports}, {_, Port} = State) + when is_list(Transports) -> CheckedTransports = - [case - case Port of - undefined -> - snmp_conf:check_address(Domain, Address); - _ -> - snmp_conf:check_address(Domain, Address, Port) - end - of - ok -> - Transport; - {ok, FixedAddress} -> - {Domain, FixedAddress} + [case Transport of + {Domain, Address} -> + case + case Port of + undefined -> + snmp_conf:check_address(Domain, Address); + _ -> + snmp_conf:check_address(Domain, Address, Port) + end + of + ok -> + Transport; + {ok, FixedAddress} -> + {Domain, FixedAddress} + end; + _ -> + error({bad_transport, Transport}) end - || {Domain, Address} = Transport <- Transports], + || Transport <- Transports], {{ok, {Tag, CheckedTransports}}, State}; check_agent(Entry, State) -> {check_agent(Entry), State}. diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl index df694ed16b..ef9503cda8 100644 --- a/lib/snmp/src/agent/snmp_target_mib.erl +++ b/lib/snmp/src/agent/snmp_target_mib.erl @@ -306,7 +306,7 @@ check_engine_id(EngineId) -> snmp_conf:check_string(EngineId). check_address(Domain, Address) -> - case snmp_conf:check_address(Domain, Address) of + case snmp_conf:check_address(Domain, Address, 162) of ok -> Address; {ok, NAddress} -> @@ -316,7 +316,11 @@ check_address(Domain, Address) -> check_mask(_Domain, [] = Mask) -> Mask; check_mask(Domain, Mask) -> - try check_address(Domain, Mask) + try snmp_conf:check_address(Domain, Mask) of + ok -> + Mask; + {ok, NMask} -> + NMask catch {error, {bad_address, Info}} -> error({bad_mask, Info}) @@ -380,16 +384,21 @@ table_del_row(Tab, Key) -> snmpa_mib_lib:table_del_row(db(Tab), Key). -add_addr(Name, Ip, Port, Timeout, Retry, TagList, - Params, EngineId, TMask, MMS) -> - Domain = default_domain(), - add_addr(Name, Domain, Ip, Port, Timeout, Retry, TagList, - Params, EngineId, TMask, MMS). - -add_addr(Name, Domain, Ip, Port, Timeout, Retry, TagList, - Params, EngineId, TMask, MMS) -> - Addr = {Name, Domain, Ip, Port, Timeout, Retry, TagList, - Params, EngineId, TMask, MMS}, +add_addr( + Name, Domain_or_Ip, Addr_or_Port, Timeout, Retry, TagList, Params, + EngineId, TMask, MMS) -> + add_addr( + {Name, Domain_or_Ip, Addr_or_Port, Timeout, Retry, TagList, Params, + EngineId, TMask, MMS}). +%% +add_addr( + Name, Domain, Ip, Port, Timeout, Retry, TagList, Params, + EngineId, TMask, MMS) -> + add_addr( + {Name, Domain, Ip, Port, Timeout, Retry, TagList, Params, + EngineId, TMask, MMS}). +%% +add_addr(Addr) -> case (catch check_target_addr(Addr)) of {ok, Row} -> Key = element(1, Row), diff --git a/lib/snmp/src/agent/snmpa_conf.erl b/lib/snmp/src/agent/snmpa_conf.erl index fe3f63c4ca..534d0e447b 100644 --- a/lib/snmp/src/agent/snmpa_conf.erl +++ b/lib/snmp/src/agent/snmpa_conf.erl @@ -47,7 +47,7 @@ read_standard_config/1, %% target_addr.conf - target_addr_entry/5, target_addr_entry/6, + target_addr_entry/5, target_addr_entry/6, target_addr_entry/7, target_addr_entry/8, target_addr_entry/10, target_addr_entry/11, write_target_addr_config/2, write_target_addr_config/3, append_target_addr_config/2, @@ -385,6 +385,12 @@ target_addr_entry( Name, Ip, TagList, ParamsName, EngineId) -> target_addr_entry(Name, Ip, TagList, ParamsName, EngineId, []). +target_addr_entry( + Name, Domain, Addr, TagList, + ParamsName, EngineId) when is_atom(Domain) -> + target_addr_entry( + Name, Domain, Addr, TagList, + ParamsName, EngineId, []); target_addr_entry( Name, Ip, TagList, ParamsName, EngineId, TMask) -> @@ -392,6 +398,13 @@ target_addr_entry( Name, Ip, 162, TagList, ParamsName, EngineId, TMask, 2048). +target_addr_entry( + Name, Domain_or_Ip, Addr_or_Port, TagList, + ParamsName, EngineId, TMask) -> + target_addr_entry( + Name, Domain_or_Ip, Addr_or_Port, TagList, + ParamsName, EngineId, TMask, 2048). + target_addr_entry( Name, Domain_or_Ip, Addr_or_Port, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> diff --git a/lib/snmp/src/manager/snmpm_conf.erl b/lib/snmp/src/manager/snmpm_conf.erl index e03d28a3e4..087ef6c6ea 100644 --- a/lib/snmp/src/manager/snmpm_conf.erl +++ b/lib/snmp/src/manager/snmpm_conf.erl @@ -200,9 +200,10 @@ do_write_users_conf(_Fd, Crap) -> %% ------ agents.conf ------ %% -agents_entry(UserId, TargetName, Comm, Ip, Port, EngineID, Timeout, - MaxMessageSize, Version, SecModel, SecName, SecLevel) -> - {UserId, TargetName, Comm, Ip, Port, EngineID, Timeout, +agents_entry( + UserId, TargetName, Comm, Domain_or_Ip, Addr_or_Port, EngineID, Timeout, + MaxMessageSize, Version, SecModel, SecName, SecLevel) -> + {UserId, TargetName, Comm, Domain_or_Ip, Addr_or_Port, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel}. diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 05d5ce72b1..940800fed4 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -1816,7 +1816,11 @@ verify_agent_config( {TD, VerifiedConf}; _ -> %% Insert tdomain since it is missing - TD = default_transport_domain(), + %% Note: not default_transport_domain() since + %% taddress is the new format hence the application + %% should be tdomain aware and therefore addresses + %% on the Domain, Addr format should be used and understood. + TD = transportDomainUdpIpv4, {TD, [{tdomain, TD}|VerifiedConf]} end, case snmp_conf:check_address(TDomain, Address, 0) of @@ -2269,15 +2273,37 @@ check_manager_config({address = Tag, Ip} = Entry, {Domain, Port} = State) -> [{Tag, FixedIp}, {transports, [{Domain, {FixedIp, Port}}]}] end, State}; -check_manager_config({transports = Tag, Transports}, State) -> +check_manager_config({transports = Tag, Transports}, {_, Port} = State) + when is_list(Transports) -> CheckedTransports = - [case snmp_conf:check_address(Domain, Address) of - ok -> - Transport; - {ok, FixedAddress} -> - {Domain, FixedAddress} + [case Transport of + {Domain, Address} -> + case + case Port of + undefined -> + snmp_conf:check_address(Domain, Address); + _ -> + snmp_conf:check_address(Domain, Address, Port) + end + of + ok -> + Transport; + {ok, FixedAddress} -> + {Domain, FixedAddress} + end; + _Domain when Port =:= undefined-> + error({missing_mandatory, port}); + Domain -> + Family = snmp_conf:tdomain_to_family(Domain), + {ok, Hostname} = inet:gethostname(), + case inet:getaddr(Hostname, Family) of + {ok, IpAddr} -> + {Domain, {IpAddr, Port}}; + {error, _} -> + error({bad_address, {Domain, Hostname}}) + end end - || {Domain, Address} = Transport <- Transports], + || Transport <- Transports], {{ok, {Tag, CheckedTransports}}, State}; check_manager_config(Entry, State) -> {check_manager_config(Entry), State}. diff --git a/lib/snmp/src/manager/snmpm_server.erl b/lib/snmp/src/manager/snmpm_server.erl index ece5dad082..a75122d0bb 100644 --- a/lib/snmp/src/manager/snmpm_server.erl +++ b/lib/snmp/src/manager/snmpm_server.erl @@ -2079,7 +2079,16 @@ do_handle_agent(DefUserId, DefMod, SnmpInfo, DefData, State) -> ?vdebug("do_handle_agent -> entry when" "~n DefUserId: ~p", [DefUserId]), - try DefMod:handle_agent(Domain, Addr, Type, SnmpInfo, DefData) of + {Domain_or_Ip, Addr_or_Port} = + case Domain of + snmpUDPDomain -> + Addr; + _ -> + {Domain, Addr} + end, + try DefMod:handle_agent( + Domain_or_Ip, Addr_or_Port, Type, SnmpInfo, DefData) + of {register, UserId2, TargetName, Config} -> ?vtrace("do_handle_agent -> register: " "~n UserId2: ~p" -- cgit v1.2.3 From fcc898b0b296376167a2a2094d0a822090cfb20e Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Fri, 29 Aug 2014 16:41:44 +0200 Subject: Update documentation --- lib/snmp/doc/src/snmp_agent_config_files.xml | 56 +++++++++++++----- lib/snmp/doc/src/snmp_agent_netif.xml | 34 +++++------ lib/snmp/doc/src/snmp_manager_config_files.xml | 63 ++++++++++++++++---- lib/snmp/doc/src/snmp_manager_netif.xml | 45 +++++++++------ lib/snmp/doc/src/snmp_target_mib.xml | 22 ++++--- lib/snmp/doc/src/snmpa_conf.xml | 66 +++++++++++++++------ lib/snmp/doc/src/snmpa_mpd.xml | 67 +++++++++++++++++----- .../doc/src/snmpa_network_interface_filter.xml | 40 ++++++++----- .../snmpa_notification_delivery_info_receiver.xml | 32 ++++++----- lib/snmp/doc/src/snmpm.xml | 14 +++-- lib/snmp/doc/src/snmpm_conf.xml | 8 +-- lib/snmp/doc/src/snmpm_mpd.xml | 14 +++-- lib/snmp/doc/src/snmpm_network_interface.xml | 12 ++-- .../doc/src/snmpm_network_interface_filter.xml | 34 ++++++----- lib/snmp/doc/src/snmpm_user.xml | 15 +++-- 15 files changed, 355 insertions(+), 167 deletions(-) diff --git a/lib/snmp/doc/src/snmp_agent_config_files.xml b/lib/snmp/doc/src/snmp_agent_config_files.xml index 1e8e879814..1e938c0dc8 100644 --- a/lib/snmp/doc/src/snmp_agent_config_files.xml +++ b/lib/snmp/doc/src/snmp_agent_config_files.xml @@ -4,7 +4,7 @@
- 19972013 + 19972014 Ericsson AB. All Rights Reserved. @@ -102,20 +102,41 @@

AgentVariable is one of the variables is SNMP-FRAMEWORK-MIB or one of the internal variables intAgentUDPPort, which defines which UDP port the agent - listens to, or intAgentIpAddress, which defines the IP - address of the agent.

+ listens to, or intAgentTransports, which defines the + transport domains and addresses of the agent.

Value is the value for the variable.

-

The following example shows a agent.conf file:

+

The following example shows an agent.conf file:

 {intAgentUDPPort, 4000}.
-{intAgentIpAddress,[141,213,11,24]}.
+{intAgentTransports,
+ [{transportDomainUdpIpv4, {141,213,11,24}},
+  {transportDomainUdpIpv6, {0,0,0,0,0,0,0,1}}]}.
 {snmpEngineID, "mbj's engine"}.
 {snmpEngineMaxPacketSize, 484}.
     
+

The value of intAgentTransports is a list of + {Domain, Addr} tuples, where Domain + is either transportDomainUdpIpv4 or transportDomainUdpIpv6, + and Addr is the address in the domain. + Addr can be specified either as an + IpAddr or as an {IpAddr, IpPort} tuple. + IpAddr is either a regular Erlang/OTP + ip_address() + or a traditional SNMP integer list and IpPort is an integer. +

+ +

When the Addr value does not contain a port number, + the value of intAgentUDPPort is used.

+ +

The legacy and intermediate variables intAgentIpAddress + and intAgentTransportDomain are still supported so old + agent.conf files will work. +

+

The value of snmpEngineID is a string, which for a deployed agent should have a very specific structure. See RFC 2271/2571 for details.

@@ -362,9 +383,9 @@ SNMP-TARGET-MIB and snmpTargetAddrExtTable in the SNMP-COMMUNITY-MIB.

Each entry is a term:

-

{TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId}.

or

-{TargetName, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.

or

-{TargetName, Domain, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.

+

{TargetName, Domain, Addr, Timeout, RetryCount, TagList, ParamsName, EngineId}. +

or

+ {TargetName, Domain, Addr, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize}.

TargetName is a unique non-empty string.

@@ -374,11 +395,14 @@ transportDomainUdpIpv4 | transportDomainUdpIpv6.

-

Ip is a list of four or eight integers.

-
- -

Udp is an integer.

+

Addr is either an IpAddr or + an {IpAddr, IpPort} tuple. IpAddr is either + a regular Erlang/OTP + ip_address() + or a traditional SNMP integer list, and IpPort is an integer.

+

If IpPort is omitted 162 is used.

+

Timeout is an integer.

@@ -395,13 +419,17 @@

EngineId is a string or the atom discovery.

-

TMask is a list of integer() of size 0, - size 6 or size 10 (default: []).

+

TMask is specified just as Addr or as []. + Note in particular that using a list of 6 bytes for IPv4 + or 8 words plus 2 bytes for IPv6 are still valid address formats + so old configurations will work.

MaxMessageSize is an integer (default: 2048).

+

The old tuple formats with Ip address and Udp + port number found in old configurations still work.

Note that if EngineId has the value discovery, the agent cannot send inform messages to that manager until it has performed the diff --git a/lib/snmp/doc/src/snmp_agent_netif.xml b/lib/snmp/doc/src/snmp_agent_netif.xml index fccfc8857a..a9ce05e757 100644 --- a/lib/snmp/doc/src/snmp_agent_netif.xml +++ b/lib/snmp/doc/src/snmp_agent_netif.xml @@ -4,7 +4,7 @@

- 19972013 + 19972014 Ericsson AB. All Rights Reserved. @@ -51,7 +51,8 @@

It is also possible to write your own Net if process. The default Net if process is implemented in the module snmpa_net_if and - it uses UDP as the transport protocol. + it uses UDP as the transport protocol i.e the transport domains + transportDomainUdpIpv4 and/or transportDomainUdpIpv6.

This section describes how to write a Net if process.

@@ -70,6 +71,12 @@

The section Messages describes mandatory messages, which Net if must send and be able to receive.

+

In this section an Address field is a + {Domain, Addr} tuple where Domain is + transportDomainUdpIpv4 or transportDomainUdpIpv4, + and Addr is an + {IpAddr, + IpPort} tuple.

@@ -96,10 +103,7 @@ MasterAgent ! {snmp_pdu, Vsn, Pdu, PduMS, ACMData, From, Extra} in use. Normally this is returned from snmpa_mpd:process_packet (see Reference Manual). - From is the source address. If UDP over IP is - used, this should be a 2-tuple {IP, UDPport}, where - IP is a 4-tuple with the IP address, and UDPport - is an integer. + From is the source Address. Extra is any term the Net if process wishes to send to the agent. This term can be retrieved by the @@ -127,10 +131,7 @@ Pid ! {snmp_response_received, Vsn, Pdu, From} Pdu is the SNMP Pdu received - From is the source address. If UDP over IP is - used, this should be a 2-tuple {IP, UDPport}, where - IP is a 4-tuple with the IP address, and UDPport - is an integer. + From is the source Address.
@@ -168,10 +169,9 @@ Pid ! {snmp_response_received, Vsn, Pdu, From} (see Reference Manual).

-

To is the destination address. If UDP over IP - is used, this should be a 2-tuple {IP, UDPport}, - where IP is a 4-tuple with the IP address, and - UDPport is an integer.

+

To is the destination Address that comes + from the From field in the corresponding snmp_pdu + message previously sent to the MasterAgent.

Extra is the term that the Net if process @@ -230,7 +230,8 @@ Pid ! {snmp_response_received, Vsn, Pdu, From} SNMPv3, it is the context information.

-

To is a list of the destination addresses and +

To is a list of {Address, SecData} + tuples i.e the destination addresses and their corresponding security parameters. This value is normally sent to snmpa_mpd:generate_message/4.

@@ -268,7 +269,8 @@ Pid ! {snmp_response_received, Vsn, Pdu, From} SNMPv3, it is the context information.

-

To is a list of the destination addresses and +

To is a list of {Address, SecData} + tuples i.e the destination addresses and their corresponding security parameters. This value is normally sent to snmpa_mpd:generate_message/4.

diff --git a/lib/snmp/doc/src/snmp_manager_config_files.xml b/lib/snmp/doc/src/snmp_manager_config_files.xml index 486ef7c170..d8bd4b0f3a 100644 --- a/lib/snmp/doc/src/snmp_manager_config_files.xml +++ b/lib/snmp/doc/src/snmp_manager_config_files.xml @@ -4,7 +4,7 @@
- 20042013 + 20042014 Ericsson AB. All Rights Reserved. @@ -64,13 +64,42 @@

Variable is one of the following:

- -

address - which defines the IP address of the - manager. Default is local host.

-
+ +

transports - which defines the transport domains + and their addresses for the manager. Mandatory +

+

Value is a list of {Domain, Addr} tuples + or Domain atoms. +

+ + +

Domain is one of transportDomainUdpIpv4 + or transportDomainUdpIpv6.

+
+ +

Addr is for the currently supported domains + either an IpAddr or an {IpAddr, IpPort} + tuple.IpAddr is either a regular Erlang/OTP + + ip_address() or a traditional SNMP integer list + and IpPort is an integer. +

+

When Addr does not contain a port number, + the value of port is used. +

+

When a Addr is not specified i.e by + using only a Domain atom, the host's name + is resolved to find the IP address, and the value of + port is used. +

+
+
+

port - which defines which UDP port the manager uses - for communicating with agents. Mandatory.

+ for communicating with agents. + Mandatory if transports does not define + a port number for every transport.

engine_id - The SnmpEngineID as defined in @@ -87,11 +116,13 @@

+

The legacy and intermediate variables address and domain + are still supported so old configurations will work.

The following example shows a manager.conf file:

-{address,          [141,213,11,24]}.
-{port,             5000}.
+{transports,       [{transportDomainUdpIpv4, {{141,213,11,24}, 5000}},
+                    {transportDomainUdpIpv6, {{0,0,0,0,0,0,0,1}, 5000}}]}.
 {engine_id,        "mgrEngine"}.
 {max_message_size, 484}.
     
@@ -146,7 +177,7 @@

Each entry is a tuple:

-

{UserId, TargetName, Comm, Ip, Port, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel}.

+

{UserId, TargetName, Comm, Domain, Addr, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel}.

UserId is the identity of the manager user @@ -160,10 +191,17 @@

Comm is the community string (string).

-

Ip is the ip address of the agent (a list of four integers).

+

Domain is the transport domain, either + transportDomainUdpIpv4 or transportDomainUdpIpv6.

-

Port is the port number of the agent (integer).

+

Addr is the address in the transport domain, + either an {IpAddr, IpPort} tuple or a traditional SNMP + integer list containing port number. IpAddr is either + a regular Erlang/OTP + ip_address() + or a traditional SNMP integer list not containing port number, + and IpPort is an integer.

EngineID is the engine-id of the agent (string).

@@ -190,6 +228,9 @@ authPriv).

+

Legacy configurations using tuples without Domain element, + as well as with all TDomain, Ip and Port elements + still work.

diff --git a/lib/snmp/doc/src/snmp_manager_netif.xml b/lib/snmp/doc/src/snmp_manager_netif.xml index 757ed32880..97cedf00c0 100644 --- a/lib/snmp/doc/src/snmp_manager_netif.xml +++ b/lib/snmp/doc/src/snmp_manager_netif.xml @@ -4,7 +4,7 @@
- 20042013 + 20042014 Ericsson AB. All Rights Reserved. @@ -50,13 +50,14 @@

The snmp application provides two different modules, snmpm_net_if (the default) and snmpm_net_if_mt, - both uses the UDP as the transport protocol. The difference - between the two modules is that the latter is "multi-threaded", - i.e. for each message/request a new process is created that - process the message/request and then exits.

+ both uses UDP as the transport protocol i.e the transport domains + transportDomainUdpIpv4 and/or transportDomainUdpIpv6. + The difference between the two modules is that the latter is + "multi-threaded", i.e. for each message/request a new process + is created that processes the message/request and then exits.

-

It is also possible to write your own Net if process, - this section describes how to write a Net if processdo that.

+

It is also possible to write your own Net if process and + this section describes how to do that.

@@ -70,11 +71,17 @@

The section Messages describes mandatory messages, which Net if must send to the manager server process.

+

In this section a Domain field is the transport domain i.e + one of transportDomainUdpIpv4 or transportDomainUdpIpv6, + and an Addr field is an + {IpAddr, + IpPort} tuple.

+

Net if must send the following message when it receives an SNMP PDU from the network that is aimed for the MasterAgent:

-Server ! {snmp_pdu, Pdu, Addr, Port}
+Server ! {snmp_pdu, Pdu, Domain, Addr}
     
@@ -82,14 +89,14 @@ Server ! {snmp_pdu, Pdu, Addr, Port} snmp_types.hrl, with the SNMP request.

-

Addr is the source address.

+

Domain is the source transport domain.

-

Port is port number of the sender.

+

Addr is the source address.

-Server ! {snmp_trap, Trap, Addr, Port}
+Server ! {snmp_trap, Trap, Domain, Addr}
     
@@ -97,14 +104,14 @@ Server ! {snmp_trap, Trap, Addr, Port} as defined in snmp_types.hrl, with the SNMP request.

-

Addr is the source address.

+

Domain is the source transport domain.

-

Port is port number of the sender.

+

Addr is the source address.

-Server ! {snmp_inform, Ref, Pdu, PduMS, Addr, Port}
+Server ! {snmp_inform, Ref, Pdu, PduMS, Domain, Addr}
     
@@ -123,14 +130,14 @@ Server ! {snmp_inform, Ref, Pdu, PduMS, Addr, Port} snmp_types.hrl, with the SNMP request.

-

Addr is the source address.

+

Domain is the source transport domain.

-

Port is port number of the sender.

+

Addr is the source address.

-Server ! {snmp_report, Data, Addr, Port}
+Server ! {snmp_report, Data, Domain, Addr}
     
@@ -152,10 +159,10 @@ Server ! {snmp_report, Data, Addr, Port}

ReasonInfo is a term().

-

Addr is the source address.

+

Domain is the source transport domain.

-

Port is port number of the sender.

+

Addr is the source address.

diff --git a/lib/snmp/doc/src/snmp_target_mib.xml b/lib/snmp/doc/src/snmp_target_mib.xml index be6fa15c73..a076ff2d8e 100644 --- a/lib/snmp/doc/src/snmp_target_mib.xml +++ b/lib/snmp/doc/src/snmp_target_mib.xml @@ -4,7 +4,7 @@
- 19982013 + 19982014 Ericsson AB. All Rights Reserved. @@ -38,18 +38,18 @@ functions for the SNMP-TARGET-MIB, and functions for configuring the database.

The configuration files are described in the SNMP User's Manual.

+

Legacy API functions add_addr/10 that does not specify + transport domain, and add_addr/11 that has got separate + IpAddr and PortNumber arguments still work as before + for backwards compatibility reasons.

DATA TYPES - +

See the + data types in snmpa_conf.

@@ -129,20 +129,18 @@ transportAddressMask() = [integer()], length 0 (default), 6 (IPv4) or 10 (IPv6) - add_addr(Name, Ip, Port, Timeout, Retry, TagList, Params, EngineId, TMask, MMS) -> Ret - add_addr(Name, Domain, Ip, Port, Timeout, Retry, TagList, Params, EngineId, TMask, MMS) -> Ret + add_addr(Name, Domain, Addr, Timeout, Retry, TagList, Params, EngineId, TMask, MMS) -> Ret Add one target address definition Name = string() Domain = transportDomain() - Ip = transportAddressIPv4() | transportAddressIPv6() (depends on the value of Domain) - Port = integer() + Addr = transportAddress() % Default port is 162 Timeout = integer() Retry = integer() TagList = string() ParamsName = string() EngineId = string() - TMask = transportAddressMask() (depends on Domain) + TMask = transportAddressMask() % Depends on Domain MMS = integer() Ret = {ok, Key} | {error, Reason} Key = term() diff --git a/lib/snmp/doc/src/snmpa_conf.xml b/lib/snmp/doc/src/snmpa_conf.xml index 99a56cd601..2780cec156 100644 --- a/lib/snmp/doc/src/snmpa_conf.xml +++ b/lib/snmp/doc/src/snmpa_conf.xml @@ -4,7 +4,7 @@
- 20062013 + 20062014 Ericsson AB. All Rights Reserved. @@ -45,20 +45,56 @@ DATA TYPES +

For inet:ip4_address(), inet:ip6_address() + and inet:port_number(), see also + + inet:ip_address()

+ + agent_entry(Tag, Val) -> agent_entry() Create an agent entry - Tag = intAgentIpAddress | intAgentUDPPort | intAgentMaxPacketSize | snmpEngineMaxMessageSize | snmpEngineID + Tag = intAgentTransports | intAgentUDPPort | intAgentMaxPacketSize | snmpEngineMaxMessageSize | snmpEngineID Val = term() agent_entry() = term() @@ -390,17 +426,15 @@ transportAddressMask() = [integer()], length 0 (default), 6 (IPv4) or 10 (IPv6) - target_addr_entry(Name, Ip, TagList, ParamsName, EngineId) -> target_addr_entry() - target_addr_entry(Name, Ip, TagList, ParamsName, EngineId, TMask) -> target_addr_entry() - target_addr_entry(Name, Ip, Udp, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry() - target_addr_entry(Name, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry() - target_addr_entry(Name, Domain, Ip, Udp, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry() + target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId) -> target_addr_entry() + target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId, TMask) -> target_addr_entry() + target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry() + target_addr_entry(Name, Domain, Addr, Timeout, RetryCount, TagList, ParamsName, EngineId, TMask, MaxMessageSize) -> target_addr_entry() Create an target_addr entry Name = string() Domain = transportDomain() - Ip = transportAddressIPv4() | transportAddressIPv6() (depends on Domain) - Udp = integer() + Ip = transportAddress() (depends on Domain) Timeout = integer() RetryCount = integer() TagList = string() @@ -414,12 +448,12 @@ transportAddressMask() = [integer()], length 0 (default), 6 (IPv4) or 10 (IPv6)

Create an entry for the agent target_addr config file, target_addr.conf.

Name must be a non-empty string.

-

target_addr_entry/5 translates to the following call: - target_addr_entry(Name, Ip, TagList, ParamsName, EngineId).

target_addr_entry/6 translates to the following call: - target_addr_entry(Name, Ip, 162, TagList, ParamsName, EngineId, TMask, 2048).

+ target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId, []).

+

target_addr_entry/7 translates to the following call: + target_addr_entry(Name, Domain, Addr, TagList, ParamsName, EngineId, TMask, 2048).

target_addr_entry/8 translates to the following call: - target_addr_entry(Name, Ip, Udp, 1500, 3, TagList, ParamsName, EngineId, TMask, MaxMessageSize).

+ target_addr_entry(Name, Domain, Addr, 1500, 3, TagList, ParamsName, EngineId, TMask, MaxMessageSize).

See Target Address Definitions for more info.

diff --git a/lib/snmp/doc/src/snmpa_mpd.xml b/lib/snmp/doc/src/snmpa_mpd.xml index c5ab0a0520..518100d30c 100644 --- a/lib/snmp/doc/src/snmpa_mpd.xml +++ b/lib/snmp/doc/src/snmpa_mpd.xml @@ -4,7 +4,7 @@
- 19992013 + 19992014 Ericsson AB. All Rights Reserved. @@ -43,6 +43,12 @@ +
+ DATA TYPES +

See the + data types in snmpa_conf.

+
+ init(Vsns) -> mpd_state() @@ -63,16 +69,17 @@ - process_packet(Packet, TDomain, TAddress, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket} - process_packet(Packet, TDomain, TAddress, LocalEngineID, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket} + process_packet(Packet, From, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket} + process_packet(Packet, From, LocalEngineID, State, NoteStore, Log) -> {ok, Vsn, Pdu, PduMS, ACMData} | {discarded, Reason} | {discovery, DiscoPacket} Process a packet received from the network Packet = binary() - TDomain = snmpUDPDomain - TAddress = {Ip, Udp} + From = {TDomain, TAddr} + TDomain = transportDomainUdpIpv4 | transportDomainUdpIpv6 + TAddr = {IpAddr, IpPort} LocalEngineID = string() - Ip = {integer(), integer(), integer(), integer()} - Udp = integer() + IpAddr = inet:ip_address() + IpPort = inet:port_number() State = mpd_state() NoteStore = pid() Log = snmp_log() @@ -85,7 +92,7 @@

Processes an incoming packet. Performs authentication and - decryption as necessary. The return values should be passed the + decryption as necessary. The return values should be passed to the agent.

@@ -150,14 +157,20 @@ network.

MsgData is the message specific data used in - the SNMP message. This value is received in a send_pdu - or send_pdu_req message from the agent. In SNMPv1 and + the SNMP message. This value is received in a + send_pdu + or + + send_pdu_req + message from the agent. In SNMPv1 and SNMPv2c, this message data is the community string. In - SNMPv3, it is the context information. - To is a list of the destination addresses and + SNMPv3, it is the context information.

+

+ To is a list of destination addresses and their corresponding security parameters. This value is - also received from the requests mentioned above. -

+ received in the same message from the agent and then transformed + trough process_taddrs + before passed to this function.

Note that the use of the LocalEngineID argument is only intended @@ -166,6 +179,32 @@ (see SNMP-FRAMEWORK-MIB).

+ +
+
+ + + process_taddrs(TDests) -> Dests + Transform addresses from internal MIB format to a less internal + + + TDests = [TDest] + TDest = {{TDomain, TAddr}, SecData} | {TDomain, TAddr} + TDomain = term() % Not at tuple + TAddr = term() + SecData = term() + Dests = [Dest] + Dest = {{Domain, Addr}, SecData} | {Domain, Addr} + Domain = transportDomain() + Addr = transportAddress() % Depends on Domain + + +

Transforms addresses from internal MIB format to one + more useful to Agent Net if. +

+

See also generate_msg. +

+
diff --git a/lib/snmp/doc/src/snmpa_network_interface_filter.xml b/lib/snmp/doc/src/snmpa_network_interface_filter.xml index e08a26ed92..eb640e1bc3 100644 --- a/lib/snmp/doc/src/snmpa_network_interface_filter.xml +++ b/lib/snmp/doc/src/snmpa_network_interface_filter.xml @@ -4,7 +4,7 @@
- 20072013 + 20072014 Ericsson AB. All Rights Reserved. @@ -58,10 +58,10 @@ on two levels:

-

The first level is at the UDP entry / exit point, i.e. - immediately after the receipt of the message, before any message +

The first level is at the transport entry / exit point, i.e. + immediately after the receipt of the message before any message processing is done (accept_recv) and - immediately before sending the message, after all message + immediately before sending the message after all message processing is done (accept_send).

@@ -78,6 +78,12 @@ req_limit and the function register_notification_filter.

+

Legacy network interface filter modules used arguments on the form + (IpAddr, PortNumber,...) instead of + (Domain, Addr, ...), and if the SNMP agent is run without + changing the configuration to use transport domains + the network interface filter will still get + the old arguments and work as before.

@@ -88,15 +94,17 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | 'set-request' | trap | 'get-bulk-request' | 'inform-request' | report +

See also the + data types in snmpa_conf.

- accept_recv(Ip, Port) -> boolean() + accept_recv(Domain, Addr) -> boolean() Shall the received message be accepted - Ip = ip_address() - Port = port() + Domain = transportDomain() + Addr = transportAddressWithPort()

Called at the reception of a message (before any processing @@ -107,11 +115,11 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | - accept_send(Ip, Port) -> boolean() + accept_send(Domain, Addr) -> boolean() Shall the message be sent - Ip = ip_address() - Port = port() + Domain = transportDomain() + Addr = transportAddressWithPort()

Called before the sending of a message (after all processing @@ -122,11 +130,11 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | - accept_recv_pdu(Ip, Port, PduType) -> boolean() + accept_recv_pdu(Domain, Addr, PduType) -> boolean() Shall the received pdu be accepted - Ip = ip_address() - Port = port() + Domain = transportDomain() + Addr = transportAddressWithPort() PduType = pdu_type() @@ -144,7 +152,9 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | Targets = targets() targets() = [target()] - target() = {ip_address(), port()} + target() = {Domain, Addr} + Domain = transportDomain() + Addr = transportAddressWithPort() PduType = pdu_type() > 0 Reply = boolean() | NewTargets NewTargets = targets() @@ -155,7 +165,7 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' |

For the message to be discarded all together, the function must return false.

Note that it is possible for this function to filter out targets - (but not add its own) by returning an updated + (but not to add its own) by returning an updated Targets list (NewTargets).

diff --git a/lib/snmp/doc/src/snmpa_notification_delivery_info_receiver.xml b/lib/snmp/doc/src/snmpa_notification_delivery_info_receiver.xml index aff71688b6..814f02a14c 100644 --- a/lib/snmp/doc/src/snmpa_notification_delivery_info_receiver.xml +++ b/lib/snmp/doc/src/snmpa_notification_delivery_info_receiver.xml @@ -5,7 +5,7 @@
2008 - 2013 + 2014 Ericsson AB, All Rights Reserved @@ -45,22 +45,30 @@ must export the following functions:

-

delivery_targets/3

+

delivery_targets/3

-

delivery_info/4

+

delivery_info/4

The semantics of them and their exact signatures are explained below.

+

Legacy notification delivery information receiver modules + used a target argument on the form + {IpAddr, PortNumber} instead of + {Domain, Addr}, and if the SNMP Agent is run without + changing the configuration to use transport domains + the notification delivery information receiver will still get + the old arguments and work as before.

+
DATA TYPES - +

See the + data types in snmpa_conf.

+
@@ -71,10 +79,8 @@ address() = A 4-tuple Inform about target addresses Tag = term() - Targets = [target()] - target() = {Address, Port} - Address = address() - Port = integer() + Targets = [Target] + Target = {transportDomain(), transportAddressWithPort() Extra = term() @@ -94,10 +100,8 @@ address() = A 4-tuple Inform about delivery result Tag = term() - Target = target() - target() = {Address, Port} - Address = address() - Port = integer() + Targets = [Target] + Target = {transportDomain(), transportAddressWithPort() DeliveryResult = delivery_result() delivery_result() = no_response | got_response Extra = term() diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml index dc8226bb87..ff90e49968 100644 --- a/lib/snmp/doc/src/snmpm.xml +++ b/lib/snmp/doc/src/snmpm.xml @@ -4,7 +4,7 @@
- 20042013 + 20042014 Ericsson AB. All Rights Reserved. @@ -69,6 +69,9 @@ sec_name() = string() sec_level() = noAuthNoPriv | authNoPriv | authPriv ]]> +

See also the + data types in snmpa_conf.

+
@@ -300,9 +303,9 @@ sec_level = noAuthNoPriv | authNoPriv | authPriv

The type of Val depends on Item:

Note that if no tdomain is given, the default value, transportDomainUdpIpv4, is used.

-

Note that if no port is given, the default value is used.

+

Note that if no port is given and if taddress does not + contain a port number, the default value is used.

diff --git a/lib/snmp/doc/src/snmpm_conf.xml b/lib/snmp/doc/src/snmpm_conf.xml index 0cc9ff3379..8635fb705b 100644 --- a/lib/snmp/doc/src/snmpm_conf.xml +++ b/lib/snmp/doc/src/snmpm_conf.xml @@ -4,7 +4,7 @@
- 20062013 + 20062014 Ericsson AB. All Rights Reserved. @@ -195,14 +195,14 @@ - agents_entry(UserId, TargetName, Comm, Ip, Port, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel) -> agents_entry() + agents_entry(UserId, TargetName, Comm, Domain, Addr, EngineID, Timeout, MaxMessageSize, Version, SecModel, SecName, SecLevel) -> agents_entry() Create an agents entry UserId = term() TargetName = string() Comm = string() - Ip = string() - Port = integer() + Domain = transportDomain() + Addr = transportAddress() EngineID = string() Timeout = integer() MaxMessageSize = integer() diff --git a/lib/snmp/doc/src/snmpm_mpd.xml b/lib/snmp/doc/src/snmpm_mpd.xml index ad72fd7bc0..c23b2b6833 100644 --- a/lib/snmp/doc/src/snmpm_mpd.xml +++ b/lib/snmp/doc/src/snmpm_mpd.xml @@ -4,7 +4,7 @@
- 20042013 + 20042014 Ericsson AB. All Rights Reserved. @@ -39,7 +39,12 @@ It is supposed to be used from a Network Interface process (Definition of Manager Net if).

+ +

Legacy API function process_msg/7 that has got separate + IpAddr and PortNumber arguments still works as before + for backwards compatibility reasons.

+ init_mpd(Vsns) -> mpd_state() @@ -58,13 +63,12 @@ - process_msg(Msg, TDomain, Addr, Port, State, NoteStore, Logger) -> {ok, Vsn, Pdu, PduMS, MsgData} | {discarded, Reason} + process_msg(Msg, Domain, Addr, State, NoteStore, Logger) -> {ok, Vsn, Pdu, PduMS, MsgData} | {discarded, Reason} Process a message received from the network Msg = binary() - TDomain = snmpUDPDomain - Addr = {integer(), integer(), integer(), integer()} - Port = integer() + Domain = transportDomainUdpIpv4 | transportDomainUdpIpv6 + Addr = {inet:ip_address(), inet:port_number()} State = mpd_state() NoteStore = pid() Logger = function() diff --git a/lib/snmp/doc/src/snmpm_network_interface.xml b/lib/snmp/doc/src/snmpm_network_interface.xml index 6cf7bd6ed7..bea6b46dc7 100644 --- a/lib/snmp/doc/src/snmpm_network_interface.xml +++ b/lib/snmp/doc/src/snmpm_network_interface.xml @@ -4,7 +4,7 @@
- 20042013 + 20042014 Ericsson AB. All Rights Reserved. @@ -69,6 +69,10 @@

The semantics of them and their exact signatures are explained below.

+

Legacy API function send_pdu/7 that has got separate + IpAddr and PortNumber arguments still works as before + for backwards compatibility reasons.

+ @@ -103,15 +107,15 @@ - send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo) -> void() + send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, ExtraInfo) -> void() Request the network interface process to send this pdu Pid = pid() Pdu = pdu() Vsn = 'version-1' | 'version-2' | 'version-3' MsgData = term() - Addr = address() - Port = integer() + Domain = transportDomainUdpIpv4 | transportDomainUdpIpv6 + Addr = {inet:ip_address(), inet:port_number()} ExtraInfo = term() diff --git a/lib/snmp/doc/src/snmpm_network_interface_filter.xml b/lib/snmp/doc/src/snmpm_network_interface_filter.xml index f0526269b3..1ef4f29c0f 100644 --- a/lib/snmp/doc/src/snmpm_network_interface_filter.xml +++ b/lib/snmp/doc/src/snmpm_network_interface_filter.xml @@ -4,7 +4,7 @@
- 20072013 + 20072014 Ericsson AB. All Rights Reserved. @@ -76,6 +76,12 @@ The default filter accepts all messages.

A network interface filter can e.g. be used during testing or for load regulation.

+

Legacy network interface filter modules used arguments on the form + (IpAddr, PortNumber,...) instead of + (Domain, Addr, ...), and if the SNMP manager is run without + changing the configuration to use transport domains + the network interface filter will still get + the old arguments and work as before.

@@ -86,16 +92,18 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | 'set-request' | trap | 'get-bulk-request' | 'inform-request' | report | trappdu +

See also the + data types in snmpa_conf.

- accept_recv(Addr, Port) -> boolean() + accept_recv(Domain, Addr) -> boolean() Shall the received message be accepted - Addr = ip_address() - Port = port() + Domain = transportDomain() + Addr = transportAddressWithPort()

Called at the reception of a message (before any processing @@ -107,11 +115,11 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | - accept_send(Addr, Port) -> boolean() + accept_send(Domain, Addr) -> boolean() Shall the message be sent - Addr = ip_address() - Port = port() + Domain = transportDomain() + Addr = transportAddressWithPort()

Called before the sending of a message (after all processing @@ -123,11 +131,11 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | - accept_recv_pdu(Addr, Port, PduType) -> boolean() + accept_recv_pdu(Domain, Addr, PduType) -> boolean() Shall the received pdu be accepted - Addr = ip_address() - Port = port() + Domain = transportDomain() + Addr = transportAddressWithPort() PduType = pdu_type() @@ -141,11 +149,11 @@ pdu_type() = 'get-request' | 'get-next-request' | 'get-response' | - accept_send_pdu(Addr, Port, PduType) -> boolean() + accept_send_pdu(Domain, Addr, PduType) -> boolean() Shall the pdu be sent - Addr = ip_address() - Port = port() + Domain = transportDomain() + Addr = transportAddressWithPort() PduType = pdu_type() > 0 diff --git a/lib/snmp/doc/src/snmpm_user.xml b/lib/snmp/doc/src/snmpm_user.xml index 6f412d90f8..a4492839cd 100644 --- a/lib/snmp/doc/src/snmpm_user.xml +++ b/lib/snmp/doc/src/snmpm_user.xml @@ -4,7 +4,7 @@

- 20042013 + 20042014 Ericsson AB. All Rights Reserved. @@ -63,10 +63,15 @@

The semantics of them and their exact signatures are explained below.

Some of the function has no defined return value (void()), - they can ofcourse return anythyng. But the functions that do have + they can of course return anything. But the functions that do have specified return value(s) must adhere to this. None of the functions can use exit of throw to return.

+

If the manager is not configured to use any particular + transport domain, the behaviour handle_agent/4 + will for backwards copmpatibility reasons be called with the old + IpAddr and PortNumber arguments

+ @@ -116,11 +121,11 @@ snmp_v1_trap_info() :: {Enteprise :: snmp:oid(), - handle_agent(Addr, Port, Type, SnmpInfo, UserData) -> Reply + handle_agent(Domain, Addr, Type, SnmpInfo, UserData) -> Reply Handle agent - Addr = ip_address() - Port = integer() + Domain = transportDomainUdpIpv4 | transportDomainUdpIpv6 + Addr = {inet:ip_address(), inet:port_number()} Type = pdu | trap | report | inform SnmpInfo = SnmpPduInfo | SnmpTrapInfo | SnmpReportInfo | SnmpInformInfo SnmpPduInfo = snmp_gen_info() -- cgit v1.2.3 From 8154921f48ad207ac292e83b9dade49ad0235e97 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 9 Sep 2014 11:57:39 +0200 Subject: Update .appup --- lib/snmp/src/app/snmp.appup.src | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index ae79e3c1d1..1cc1a17b1d 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -28,6 +28,7 @@ %% {update, snmpa_local_db, soft, soft_purge, soft_purge, []} %% {add_module, snmpm_net_if_mt} [ + {"5.0", [{restart_application, snmp}]}, {"4.25.1", [{restart_application, snmp}]}, {"4.25.0.1", [{restart_application, snmp}]}, {"4.25", [{restart_application, snmp}]}, @@ -42,6 +43,7 @@ %% {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} [ + {"5.0", [{restart_application, snmp}]}, {"4.25.1", [{restart_application, snmp}]}, {"4.25.0.1", [{restart_application, snmp}]}, {"4.25", [{restart_application, snmp}]}, -- cgit v1.2.3 From f1ec7172f48f16e399ae07db2260195432661d07 Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 9 Sep 2014 14:53:06 +0200 Subject: Fix manager backwards compat for agent addr --- lib/snmp/src/manager/snmpm_config.erl | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 940800fed4..24adb8a47f 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -442,8 +442,31 @@ agent_info(TargetName, all) -> All -> {ok, [{Item, Val} || {{_, Item}, Val} <- All]} end; +%% Begin backwards compatibility +agent_info(TargetName, address) -> + case agent_info({TargetName, taddress}) of + {ok, Val} -> + {Addr, _} = Val, + {ok, Addr}; + _ -> + %% This should be redundant since 'taddress' should exist + agent_info({TargetName, address}) + end; +agent_info(TargetName, port) -> + case agent_info({TargetName, taddress}) of + {ok, Val} -> + {_, Port} = Val, + {ok, Port}; + _ -> + %% This should be redundant since 'taddress' should exist + agent_info({TargetName, port}) + end; +%% End backwards compatibility agent_info(TargetName, Item) -> - case ets:lookup(snmpm_agent_table, {TargetName, Item}) of + agent_info({TargetName, Item}). + +agent_info(Key) -> + case ets:lookup(snmpm_agent_table, Key) of [{_, Val}] -> {ok, Val}; [] -> -- cgit v1.2.3 From c8d593b389188dc2111015b56d6c218633804bef Mon Sep 17 00:00:00 2001 From: Raimo Niskanen Date: Tue, 9 Sep 2014 15:12:32 +0200 Subject: Remove debug printouts --- lib/snmp/src/manager/snmpm_config.erl | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index 24adb8a47f..5cab81baf6 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -479,29 +479,29 @@ agent_info(Domain, Address, Item) when is_atom(Domain) -> do_agent_info(Domain, NAddress, Item) catch _Thrown -> - p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n" - " ~p", - [Domain, Address, Item, _Thrown, erlang:get_stacktrace()]), + %% p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n" + %% " ~p", + %% [Domain, Address, Item, _Thrown, erlang:get_stacktrace()]), {error, not_found} end; agent_info(Ip, Port, Item) when is_integer(Port) -> - p(?MODULE_STRING":agent_info(~p, ~p, ~p) entry~n", - [Ip, Port, Item]), + %% p(?MODULE_STRING":agent_info(~p, ~p, ~p) entry~n", + %% [Ip, Port, Item]), Domain = default_transport_domain(), try fix_address(Domain, {Ip, Port}) of Address -> do_agent_info(Domain, Address, Item) catch _Thrown -> - p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n" - " ~p", - [Ip, Port, Item, _Thrown, erlang:get_stacktrace()]), + %% p(?MODULE_STRING":agent_info(~p, ~p, ~p) throwed ~p at.~n" + %% " ~p", + %% [Ip, Port, Item, _Thrown, erlang:get_stacktrace()]), {error, not_found} end. do_agent_info(Domain, Address, target_name = Item) -> - p(?MODULE_STRING":do_agent_info(~p, ~p, ~p) entry~n", - [Domain, Address, Item]), + %% p(?MODULE_STRING":do_agent_info(~p, ~p, ~p) entry~n", + %% [Domain, Address, Item]), case ets:lookup(snmpm_agent_table, {Domain, Address, Item}) of [{_, Val}] -> {ok, Val}; @@ -509,8 +509,8 @@ do_agent_info(Domain, Address, target_name = Item) -> {error, not_found} end; do_agent_info(Domain, Address, Item) -> - p(?MODULE_STRING":do_agent_info(~p, ~p, ~p) entry~n", - [Domain, Address, Item]), + %% p(?MODULE_STRING":do_agent_info(~p, ~p, ~p) entry~n", + %% [Domain, Address, Item]), case do_agent_info(Domain, Address, target_name) of {ok, TargetName} -> agent_info(TargetName, Item); @@ -3431,5 +3431,5 @@ error_msg(F, A) -> %% p(F) -> %% p(F, []). -p(F, A) -> - io:format("~w:" ++ F ++ "~n", [?MODULE | A]). +%% p(F, A) -> +%% io:format("~w:" ++ F ++ "~n", [?MODULE | A]). -- cgit v1.2.3