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/manager/snmpm_net_if_mt.erl') 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_mt.erl | 217 +------------------------------ 1 file changed, 4 insertions(+), 213 deletions(-) (limited to 'lib/snmp/src/manager/snmpm_net_if_mt.erl') 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 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/snmpm_net_if_mt.erl | 1340 +----------------------------- 1 file changed, 3 insertions(+), 1337 deletions(-) (limited to 'lib/snmp/src/manager/snmpm_net_if_mt.erl') 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