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(-) (limited to 'lib/snmp/src') 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 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 ++++++++++++++++++++----------- 1 file changed, 520 insertions(+), 279 deletions(-) (limited to 'lib/snmp/src') 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 -- 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(-) (limited to 'lib/snmp/src') 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 ++++++-- 5 files changed, 46 insertions(+), 15 deletions(-) (limited to 'lib/snmp/src') 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}], -- 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(-) (limited to 'lib/snmp/src') 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 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(-) (limited to 'lib/snmp/src') 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 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(+) (limited to 'lib/snmp/src') 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(-) (limited to 'lib/snmp/src') 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(-) (limited to 'lib/snmp/src') 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