snmpm_net_if.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 855 行 · 第 1/2 页
ERL
855 行
%% ``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%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(snmpm_net_if).-behaviour(gen_server).-behaviour(snmpm_network_interface).%% Network Interface callback functions-export([ start_link/2, stop/1, send_pdu/6, % Backward compatibillity send_pdu/7, inform_response/4, note_store/2, info/1, verbosity/2 ]).%% 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, sock, mpd_state, log, irb = auto, % auto | {user, integer()} irgc }).-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)).%%%-------------------------------------------------------------------%%% 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, Addr, Port) -> send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, undefined).send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo) when record(Pdu, pdu) -> ?d("send_pdu -> entry with" "~n Pid: ~p" "~n Pdu: ~p" "~n Vsn: ~p" "~n MsgData: ~p" "~n Addr: ~p" "~n Port: ~p", [Pid, Pdu, Vsn, MsgData, Addr, Port]), cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo}).note_store(Pid, NoteStore) -> call(Pid, {note_store, NoteStore}).inform_response(Pid, Ref, Addr, Port) -> cast(Pid, {inform_response, Ref, Addr, Port}).info(Pid) -> call(Pid, info).verbosity(Pid, V) -> call(Pid, {verbosity, V}).%%%-------------------------------------------------------------------%%% 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]), 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), %% -- Prio -- {ok, Prio} = snmpm_config:system_info(prio), process_flag(priority, Prio), %% -- Create inform request table -- ets:new(snmpm_inform_request_table, [set, protected, 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), %% -- 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), %% -- 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), {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, BindTo, NoReuse), %% -- Audit trail log --- {ok, ATL} = snmpm_config:system_info(audit_trail_log), Log = do_init_log(ATL), %% -- We are done --- State = #state{server = Server, note_store = NoteStore, mpd_state = MpdState, sock = Sock, log = Log, irb = IRB, irgc = IrGcRef}, ?vdebug("started", []), {ok, State}.%% Open port do_open_port(Port, SendSz, RecvSz, BindTo, NoReuse) -> ?vtrace("do_open_port -> entry with" "~n Port: ~p" "~n SendSz: ~p" "~n RecvSz: ~p" "~n BindTo: ~p" "~n NoReuse: ~p", [Port, SendSz, RecvSz, BindTo, NoReuse]), IpOpts1 = bind_to(BindTo), IpOpts2 = no_reuse(NoReuse), IpOpts3 = recbuf(RecvSz), IpOpts4 = sndbuf(SendSz), IpOpts = [binary | IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], 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.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(_) -> [].no_reuse(false) -> [{reuseaddr, true}];no_reuse(_) -> [].recbuf(default) -> [];recbuf(Sz) -> [{recbuf, Sz}].sndbuf(default) -> [];sndbuf(Sz) -> [{sndbuf, Sz}].%% Open logdo_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 snmp_log:create(Name, File, Size, Repair, true) of {ok, Log} -> {Log, Type}; {error, Reason} -> throw({error, {failed_create_audit_log, Reason}}) 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({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, Addr, Port, _ExtraInfo}, State) -> ?vlog("received send_pdu message with" "~n Pdu: ~p" "~n Vsn: ~p" "~n MsgData: ~p" "~n Addr: ~p" "~n Port: ~p", [Pdu, Vsn, MsgData, Addr, Port]), handle_send_pdu(Pdu, Vsn, MsgData, Addr, Port, State), {noreply, State};handle_cast({inform_response, Ref, Addr, Port}, State) -> ?vlog("received inform_response message with" "~n Ref: ~p" "~n Addr: ~p" "~n Port: ~p", [Ref, Addr, Port]), handle_inform_response(Ref, Addr, Port, State), {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, Sock, Ip, Port, Bytes}, #state{sock = Sock} = State) -> ?vlog("received ~w bytes from ~p:~p [~w]", [size(Bytes), Ip, Port, Sock]), handle_recv_msg(Ip, Port, Bytes, State), {noreply, State};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(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({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({down, _Vsn}, OldState, downgrade_to_pre45) -> ?d("code_change(down) -> entry", []), #state{server = Server, note_store = NoteStore, sock = Sock, mpd_state = MpdState, log = Log, irgc = IrGcRef} = OldState, irgc_stop(IrGcRef), (catch ets:delete(snmpm_inform_request_table)), State = {state, Server, NoteStore, Sock, MpdState, Log}, {ok, State};% upgradecode_change(_Vsn, OldState, upgrade_from_pre45) -> ?d("code_change(up) -> entry", []), {state, Server, NoteStore, Sock, MpdState, Log} = OldState, State = #state{server = Server, note_store = NoteStore, sock = Sock, mpd_state = MpdState, log = Log, irb = auto, irgc = undefined}, ets:new(snmpm_inform_request_table, [set, protected, named_table, {keypos, 1}]), {ok, State};code_change(_Vsn, State, _Extra) -> {ok, State}. %%%-------------------------------------------------------------------%%% Internal functions%%%-------------------------------------------------------------------handle_recv_msg(Addr, Port, Bytes, #state{server = Pid}) when is_binary(Bytes) and (size(Bytes) == 0) -> Pid ! {snmp_error, {empty_message, Addr, Port}, Addr, Port}, ok;handle_recv_msg(Addr, Port, Bytes, #state{server = Pid, note_store = NoteStore, mpd_state = MpdState, sock = Sock, log = Log, irb = IRB}) -> Logger = logger(Log, read, Addr, Port), case (catch snmpm_mpd:process_msg(Bytes, snmpUDPDomain, Addr, Port, MpdState, NoteStore, Logger)) of %% BMK BMK BMK %% Do we really need message size here??
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?