<commit_before>%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1996-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%%     http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
-module(snmpa_trap).

%%%-----------------------------------------------------------------
%%% This module takes care of all trap(notification handling.
%%%-----------------------------------------------------------------
%% External exports
-export([construct_trap/2, 
	 try_initialise_vars/2, 
	 send_trap/6, send_trap/7, send_trap/8]).
-export([send_discovery/6]).

%% Internal exports
-export([init_v2_inform/9, init_v2_inform/10, 
	 init_v3_inform/9, init_v3_inform/10, init_v3_inform/11, 
	 send_inform/6]).
-export([init_discovery_inform/13, send_discovery_inform/5]).

%% <BACKWARD-COMPAT>
-export([send_discovery/5, 
	 init_discovery_inform/12]).
%% </BACKWARD-COMPAT>

-include_lib("snmp/include/snmp_types.hrl").
-include_lib("snmp/src/agent/snmpa_internal.hrl").
-include_lib("snmp/include/SNMPv2-MIB.hrl").
-include_lib("snmp/include/SNMPv2-TM.hrl").
-include_lib("snmp/include/SNMPv2-TC.hrl").
-include_lib("snmp/include/SNMP-FRAMEWORK-MIB.hrl").
-include_lib("snmp/include/SNMP-TARGET-MIB.hrl").
-include_lib("snmp/include/TRANSPORT-ADDRESS-MIB.hrl").
-define(enterpriseSpecific, 6).


-define(VMODULE,"TRAP").
-include("snmp_verbosity.hrl").
-include("snmpa_internal.hrl").


%%-----------------------------------------------------------------
%% Trap mechanism
%% ==============
%% Distributed subagent (dSA) case
%%   The MIB with the TRAP-TYPE macro is loaded in dSA.  This means
%%   that dSA has info on all variables defined in the TRAP-TYPE,
%%   even though some variables may be located in other SA:s (or
%%   in the MA). Other variables that may be sent in the trap, 
%%   must be known by either the dSA, or some of its parent agents
%%   (e.g. the master agent), if the variable should be referred
%%   to by symbolic name. It is however possible to send other
%%   variables as well, but then the entire OID must be provided.
%%   The dSA locates the asn1 type, oid and value for as many
%%   variables as possible. This information, together with the
%%   variables for which the type, value or oid isn't known, is
%%   sent to the dSA's parent. This agent performs the same
%%   operation, and so on, until eventually the MA will receive the
%%   info. The MA then fills in the gaps, and at this point all
%%   oids and types must be known, otherwise an error is signalled,
%%   and the opertaion is aborted. For the unknown values for some 
%%   oids, a get-operation is performed by the MA. This will
%%   retreive the missing values.
%%   At this point, all oid, types and values are known, so the MA
%%   can distribute the traps according to the information in the
%%   internal tables.
%% 
%% Local subagent (lSA) case
%%   This case is similar to the case above.
%%
%% Master agent (MA) case
%%   This case is similar to the case above.
%%
%% NOTE: All trap forwarding between agents is made asynchronously.
%%
%% dSA: Distributed SA  (the #trap is loaded here)
%% nSA: [many] SAs between dSA and MA
%% MA:  Master Agent. (all trap info (destiniations is here))
%% 1) application decides to send a trap.
%% 2) dSA calls send_trap which initialises vars
%% 3) dSA sends all to nSA
%% 4) nSA tries to map symbolic names to oids and find the types
%%    of all variableoids with a value (and no type).
%% 5) nSA sends all to (n-1)SA
%% 6) MA tries to initialise vars
%% 7) MA makes a trappdu, and sends it to all destination.
%%
%% Problems with this implementation
%% =================================
%% It's ok to send {Oid, Value} but not just Oid. (it should be for
%%   any Oid)
%% It's ok to send {Name, Value} but not just Name. (it should be
%%   for Names in the hierarchy)
%% This approach might be too flexible; will people use it?
%% *NOTE*
%% Therefore, in this version we *do not* allow extra variables
%% in traps.
%% *YES* In _this_ version we do.
%%-----------------------------------------------------------------

%%-----------------------------------------------------------------
%% Func: construct_trap/2
%% Args: Trap is an atom
%%       Varbinds is a list of 
%%               {Variable, Value} | {SymbolicTableCol, RowIndex, Value} 
%%         where Variable is an atom or an OID, 
%%         where RowIndex is the indexes for the row.
%%         We don't check the RowIndex.
%% Purpose: This is the initially-called function. It is called
%%          by the agent that found out that a trap should be
%%          sent.
%%          Initialize as many variables as possible.
%% Returns: {ok, TrapRecord, <list of Var>} | error
%%          where Var is returned from initiate_vars.
%% NOTE: Executed at the inital SA
%%-----------------------------------------------------------------
construct_trap(Trap, Varbinds) ->
    ?vdebug("construct_trap -> entry with"
            "~n   Trap: ~p", [Trap]),
    case snmpa_symbolic_store:get_notification(Trap) of
	undefined -> 
	    user_err("construct_trap got undef Trap: ~w" , [Trap]),
	    error;

	{value, #trap{oidobjects = ListOfVars} = TRec} ->
	    ?vdebug("construct_trap -> trap"
		    "~n   ~p", [TRec]),
	    OidVbs        = [alias_to_oid(Vb) || Vb <- Varbinds],
	    LV            = initiate_vars(ListOfVars, OidVbs),
	    InitiatedVars = try_initialise_vars(get(mibserver), LV),
	    {ok, TRec, InitiatedVars};

	{value, #notification{oidobjects = ListOfVars} = NRec} ->
	    ?vdebug("construct_trap -> notification"
		    "~n   ~p", [NRec]),
	    OidVbs        = [alias_to_oid(Vb) || Vb <- Varbinds],
	    LV            = initiate_vars(ListOfVars, OidVbs),
	    InitiatedVars = try_initialise_vars(get(mibserver), LV), 
	    {ok, NRec, InitiatedVars}
    end.

alias_to_oid({Alias, Val}) when is_atom(Alias) ->
    case snmpa_symbolic_store:aliasname_to_oid(Alias) of
	{value, Oid} -> {lists:append(Oid, [0]), {value, Val}};
	_ ->   	     {Alias, {value, Val}}
    end;
alias_to_oid({Alias, RowIndex, Val}) when is_atom(Alias) ->
    case snmpa_symbolic_store:aliasname_to_oid(Alias) of
	{value, Oid} -> {lists:append(Oid, RowIndex), {value, Val}};
	_ ->   	     {Alias, RowIndex, {value, Val}}
    end;
alias_to_oid({Oid, Val}) -> {Oid, {value, Val}}.


%%-----------------------------------------------------------------
%% Func: initiate_vars/2
%% Args: ListOfVars is a list of {Oid, #asn1_type}
%%       Varbinds is a list of 
%%          {VariableOid, Value} | 
%%          {VariableAtom, Value} |
%%          {TableColAtom, RowIndex, Value}
%% Purpose: For each variable specified in the TRAP-TYPE macro
%%          (each in ListOfVars), check if it's got a value given
%%          in the Varbinds list.
%%          For each Oid:
%%            1) It has corresponding VariableOid. Use Value.
%%            2) No corresponding VariableOid. No value.
%% Returns: A list of
%%            {VariableOid, #asn1_type, Value} |
%%            {VariableOid, #asn1_type} |
%%            {VariableOid, Value} |
%%            {VariableAtom, Value} |
%%            {TableColAtom, RowIndex, Value}
%% NOTE: Executed at the inital SA
%%-----------------------------------------------------------------
initiate_vars([{Oid, Asn1Type} | T], Varbinds) ->
    case delete_oid_from_varbinds(Oid, Varbinds) of
	{undefined, _, _} ->
	    [{Oid, Asn1Type} | initiate_vars(T, Varbinds)];
	{?NOTIFICATION_IGNORE_VB_VALUE, _VarOid, RestOfVarbinds} -> % Skip this oid!
	    initiate_vars(T, RestOfVarbinds);<commit_msg>[snmp|agent] Fixed value selection<commit_after>%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1996-2019. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%%     http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
-module(snmpa_trap).

%%%-----------------------------------------------------------------
%%% This module takes care of all trap(notification handling.
%%%-----------------------------------------------------------------
%% External exports
-export([construct_trap/2, 
	 try_initialise_vars/2, 
	 send_trap/6, send_trap/7, send_trap/8]).
-export([send_discovery/6]).

%% Internal exports
-export([init_v2_inform/9, init_v2_inform/10, 
	 init_v3_inform/9, init_v3_inform/10, init_v3_inform/11, 
	 send_inform/6]).
-export([init_discovery_inform/13, send_discovery_inform/5]).

%% <BACKWARD-COMPAT>
-export([send_discovery/5, 
	 init_discovery_inform/12]).
%% </BACKWARD-COMPAT>

-include_lib("snmp/include/snmp_types.hrl").
-include_lib("snmp/src/agent/snmpa_internal.hrl").
-include_lib("snmp/include/SNMPv2-MIB.hrl").
-include_lib("snmp/include/SNMPv2-TM.hrl").
-include_lib("snmp/include/SNMPv2-TC.hrl").
-include_lib("snmp/include/SNMP-FRAMEWORK-MIB.hrl").
-include_lib("snmp/include/SNMP-TARGET-MIB.hrl").
-include_lib("snmp/include/TRANSPORT-ADDRESS-MIB.hrl").
-define(enterpriseSpecific, 6).


-define(VMODULE,"TRAP").
-include("snmp_verbosity.hrl").
-include("snmpa_internal.hrl").


%%-----------------------------------------------------------------
%% Trap mechanism
%% ==============
%% Distributed subagent (dSA) case
%%   The MIB with the TRAP-TYPE macro is loaded in dSA.  This means
%%   that dSA has info on all variables defined in the TRAP-TYPE,
%%   even though some variables may be located in other SA:s (or
%%   in the MA). Other variables that may be sent in the trap, 
%%   must be known by either the dSA, or some of its parent agents
%%   (e.g. the master agent), if the variable should be referred
%%   to by symbolic name. It is however possible to send other
%%   variables as well, but then the entire OID must be provided.
%%   The dSA locates the asn1 type, oid and value for as many
%%   variables as possible. This information, together with the
%%   variables for which the type, value or oid isn't known, is
%%   sent to the dSA's parent. This agent performs the same
%%   operation, and so on, until eventually the MA will receive the
%%   info. The MA then fills in the gaps, and at this point all
%%   oids and types must be known, otherwise an error is signalled,
%%   and the opertaion is aborted. For the unknown values for some 
%%   oids, a get-operation is performed by the MA. This will
%%   retreive the missing values.
%%   At this point, all oid, types and values are known, so the MA
%%   can distribute the traps according to the information in the
%%   internal tables.
%% 
%% Local subagent (lSA) case
%%   This case is similar to the case above.
%%
%% Master agent (MA) case
%%   This case is similar to the case above.
%%
%% NOTE: All trap forwarding between agents is made asynchronously.
%%
%% dSA: Distributed SA  (the #trap is loaded here)
%% nSA: [many] SAs between dSA and MA
%% MA:  Master Agent. (all trap info (destiniations is here))
%% 1) application decides to send a trap.
%% 2) dSA calls send_trap which initialises vars
%% 3) dSA sends all to nSA
%% 4) nSA tries to map symbolic names to oids and find the types
%%    of all variableoids with a value (and no type).
%% 5) nSA sends all to (n-1)SA
%% 6) MA tries to initialise vars
%% 7) MA makes a trappdu, and sends it to all destination.
%%
%% Problems with this implementation
%% =================================
%% It's ok to send {Oid, Value} but not just Oid. (it should be for
%%   any Oid)
%% It's ok to send {Name, Value} but not just Name. (it should be
%%   for Names in the hierarchy)
%% This approach might be too flexible; will people use it?
%% *NOTE*
%% Therefore, in this version we *do not* allow extra variables
%% in traps.
%% *YES* In _this_ version we do.
%%-----------------------------------------------------------------

%%-----------------------------------------------------------------
%% Func: construct_trap/2
%% Args: Trap is an atom
%%       Varbinds is a list of 
%%               {Variable, Value} | {SymbolicTableCol, RowIndex, Value} 
%%         where Variable is an atom or an OID, 
%%         where RowIndex is the indexes for the row.
%%         We don't check the RowIndex.
%% Purpose: This is the initially-called function. It is called
%%          by the agent that found out that a trap should be
%%          sent.
%%          Initialize as many variables as possible.
%% Returns: {ok, TrapRecord, <list of Var>} | error
%%          where Var is returned from initiate_vars.
%% NOTE: Executed at the inital SA
%%-----------------------------------------------------------------
construct_trap(Trap, Varbinds) ->
    ?vdebug("construct_trap -> entry with"
            "~n   Trap: ~p", [Trap]),
    case snmpa_symbolic_store:get_notification(Trap) of
	undefined -> 
	    user_err("construct_trap got undef Trap: ~w" , [Trap]),
	    error;

	{value, #trap{oidobjects = ListOfVars} = TRec} ->
	    ?vdebug("construct_trap -> trap"
		    "~n   ~p", [TRec]),
	    OidVbs        = [alias_to_oid(Vb) || Vb <- Varbinds],
	    LV            = initiate_vars(ListOfVars, OidVbs),
	    InitiatedVars = try_initialise_vars(get(mibserver), LV),
	    {ok, TRec, InitiatedVars};

	{value, #notification{oidobjects = ListOfVars} = NRec} ->
	    ?vdebug("construct_trap -> notification"
		    "~n   ~p", [NRec]),
	    OidVbs        = [alias_to_oid(Vb) || Vb <- Varbinds],
	    LV            = initiate_vars(ListOfVars, OidVbs),
	    InitiatedVars = try_initialise_vars(get(mibserver), LV), 
	    {ok, NRec, InitiatedVars}
    end.

alias_to_oid({Alias, Val}) when is_atom(Alias) ->
    case snmpa_symbolic_store:aliasname_to_oid(Alias) of
	{value, Oid} -> {lists:append(Oid, [0]), {value, Val}};
	_ ->   	     {Alias, {value, Val}}
    end;
alias_to_oid({Alias, RowIndex, Val}) when is_atom(Alias) ->
    case snmpa_symbolic_store:aliasname_to_oid(Alias) of
	{value, Oid} -> {lists:append(Oid, RowIndex), {value, Val}};
	_ ->   	     {Alias, RowIndex, {value, Val}}
    end;
alias_to_oid({Oid, Val}) -> {Oid, {value, Val}}.


%%-----------------------------------------------------------------
%% Func: initiate_vars/2
%% Args: ListOfVars is a list of {Oid, #asn1_type}
%%       Varbinds is a list of 
%%          {VariableOid, Value} | 
%%          {VariableAtom, Value} |
%%          {TableColAtom, RowIndex, Value}
%% Purpose: For each variable specified in the TRAP-TYPE macro
%%          (each in ListOfVars), check if it's got a value given
%%          in the Varbinds list.
%%          For each Oid:
%%            1) It has corresponding VariableOid. Use Value.
%%            2) No corresponding VariableOid. No value.
%% Returns: A list of
%%            {VariableOid, #asn1_type, Value} |
%%            {VariableOid, #asn1_type} |
%%            {VariableOid, Value} |
%%            {VariableAtom, Value} |
%%            {TableColAtom, RowIndex, Value}
%% NOTE: Executed at the inital SA
%%-----------------------------------------------------------------
initiate_vars([{Oid, Asn1Type} | T], Varbinds) ->
    case delete_oid_from_varbinds(Oid, Varbinds) of
	{undefined, _, _} ->
	    [{Oid, Asn1Type} | initiate_vars(T, Varbinds)];
        %% Skip this oid!
	{{value, ?NOTIFICATION_IGNORE_VB_VALUE}, _VarOid, RestOfVarbinds} ->
	    initiate_vars(T, RestOfVarbinds);
{'fraction_non_alphanumeric': 0.1867240626364714, 'fraction_numerical': 0.007611204691496662, 'mean_word_length': 2.622598870056497, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5755111', 'n_tokens_mistral': 5131, 'n_tokens_neox': 4921, 'n_words': 1679}