1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2019-2019. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22%% Note that most of these functions *assume* that they are executed
23%% by the agent. If they are not they may note work as they require
24%% some properties to be set in the process dictionary!
25%%
26
27-module(snmpa_get_lib).
28
29-export([
30         split_vbs/1, split_vbs/3,
31         split_vbs_view/2,
32         split_vbs_gb/2,
33
34         agent_sort_vbs/1,
35         oid_sort_vbs/1, org_index_sort_vbs/1,
36
37         sa_split/1,
38
39         delete_prefixes/2,
40
41         dbg_apply/3,
42
43         user_err/2
44        ]).
45
46-define(VMODULE,"GET-LIB").
47-include("snmpa_internal.hrl").
48-include("snmp_types.hrl").
49-include("snmp_debug.hrl").
50-include("snmp_verbosity.hrl").
51
52
53
54
55%%-----------------------------------------------------------------
56%% split_vbs/1,3
57%%
58%% Splits the list of varbinds (basically) into two lists. One
59%% of 'end of'-varbinds (mib view and tables) and then the rest
60%% of the varbinds.
61%%-----------------------------------------------------------------
62
63-spec split_vbs(VBs :: [snmp:varbind()]) ->
64                       {ResVBs   :: [snmp:varbind()],
65                        EndOfVBs :: [snmp:varbind()]}.
66
67split_vbs(VBs) ->
68    split_vbs(VBs, [], []).
69
70-spec split_vbs(VBs    :: [snmp:varbind()],
71                Res    :: [snmp:varbind()],
72                EndOfs :: [snmp:varbind()]) ->
73                       {ResVBs   :: [snmp:varbind()],
74                        EndOfVBs :: [snmp:varbind()]}.
75
76split_vbs([], ResVBs, EndOfVBs) ->
77    {ResVBs, EndOfVBs};
78split_vbs([VB | VBs], Res, EndOfs) ->
79    case VB#varbind.value of
80        {endOfMibView, _} -> split_vbs(VBs, Res, [VB | EndOfs]);
81        {endOfTable, _}   -> split_vbs(VBs, Res, [VB | EndOfs]);
82        _                 -> split_vbs(VBs, [VB | Res], EndOfs)
83    end.
84
85
86
87%%-----------------------------------------------------------------
88%% split_vbs_view/2
89%%
90%% Splits a list of varbinds into two lists based on the provided
91%% MibView. One list of varbinds inside the MibView and one of
92%% varbinds outside the MibView.
93%%-----------------------------------------------------------------
94
95-spec split_vbs_view(VBs     :: [snmp:varbind()],
96                     MibView :: snmp_view_based_acm_mib:mibview()) ->
97                            {OutSideView :: [snmp:varbind()],
98                             InSideView  :: [snmp:varbind()]}.
99
100split_vbs_view(VBs, MibView) ->
101    ?vtrace("split the varbinds view", []),
102    split_vbs_view(VBs, MibView, [], []).
103
104split_vbs_view([], _MibView, Out, In) ->
105    {Out, In};
106split_vbs_view([VB | VBs], MibView, Out, In) ->
107    case snmpa_acm:validate_mib_view(VB#varbind.oid, MibView) of
108	true ->
109            split_vbs_view(VBs, MibView, Out, [VB | In]);
110	false ->
111            VB2 = VB#varbind{value = noSuchObject},
112            split_vbs_view(VBs, MibView, [VB2 | Out], In)
113    end.
114
115
116
117%%-----------------------------------------------------------------
118%% split_vbs_gb/2
119%%
120%% Performs a get-bulk split of the varbinds
121%%-----------------------------------------------------------------
122
123-spec split_vbs_gb(NonRepeaters :: integer(),
124                   VBs          :: [snmp:varbind()]) ->
125                          {NonRepVBs :: [snmp:varbind()],
126                           RestVBs   :: [snmp:varbind()]}.
127
128split_vbs_gb(N, VBs) ->
129    split_vbs_gb(N, VBs, []).
130
131split_vbs_gb(N, Varbinds, Res) when N =< 0 ->
132    {Res, Varbinds};
133split_vbs_gb(N, [H | T], Res) ->
134    split_vbs_gb(N-1, T, [H | Res]);
135split_vbs_gb(_N, [], Res) ->
136    {Res, []}.
137
138
139
140%%-----------------------------------------------------------------
141%% agent_sort_vbs/1
142%%
143%% Sorts the varbinds into two categories. The first is varbinds
144%% belonging to "our" agent and the other is varbinds for
145%% subagents.
146%%-----------------------------------------------------------------
147
148-spec agent_sort_vbs(VBs :: [snmp:varbind()]) ->
149                      {AgentVBs    :: [snmp:varbind()],
150                       SubAgentVBs :: [snmp:varbind()]}.
151
152agent_sort_vbs(VBs) ->
153    snmpa_svbl:sort_varbindlist(get(mibserver), VBs).
154
155
156%%-----------------------------------------------------------------
157%% oid_sort_vbs/1
158%%
159%% Sorts the varbinds based on their oid.
160%%-----------------------------------------------------------------
161
162-spec oid_sort_vbs(VBs :: [snmp:varbind()]) -> SortedVBs :: [snmp:varbind()].
163
164oid_sort_vbs(VBs) ->
165    lists:keysort(#varbind.oid, VBs).
166
167
168%%-----------------------------------------------------------------
169%% org_index_sort_vbs/1
170%%
171%% Sorts the varbinds based on their org_index.
172%%-----------------------------------------------------------------
173
174-spec org_index_sort_vbs(VBs :: [snmp:varbind()]) -> SortedVBs :: [snmp:varbind()].
175
176org_index_sort_vbs(Vbs) ->
177    lists:keysort(#varbind.org_index, Vbs).
178
179
180
181%%-----------------------------------------------------------------
182%% sa_split/1
183%%
184%% Splits a list of {oid(), varbind()} into two lists of oid()
185%% and varbind. The resulting lists are reversed!
186%%-----------------------------------------------------------------
187
188-spec sa_split(SAVBs :: [{SAOid :: snmp:oid(), snmp:varbind()}]) ->
189                      {Oids :: [snmp:oid()], VBs :: [snmp:varbind()]}.
190
191sa_split(SAVBs) ->
192    snmpa_svbl:sa_split(SAVBs).
193
194
195
196%%-----------------------------------------------------------------
197%% delete_prefixes/2
198%%
199%% Takes an Oid prefix and a list of ivarbinds and produces a list
200%% of {ShortOid, ASN1Type}. The ShortOid is basically the oid with
201%% the OidPrefix removed.
202%%-----------------------------------------------------------------
203
204-spec delete_prefixes(OidPrefix :: snmp:oid(),
205                      VBs       :: [snmp:ivarbind()]) ->
206                             [{ShortOid :: snmp:oid(),
207                               ASN1Type :: snmp:asn1_type()}].
208
209delete_prefixes(OidPrefix, IVBs) ->
210    [{snmp_misc:diff(Oid, OidPrefix), ME#me.asn1_type} ||
211        #ivarbind{varbind = #varbind{oid = Oid}, mibentry = ME} <- IVBs].
212
213
214
215%%-----------------------------------------------------------------
216%% dbg_apply/3
217%%
218%% Call instrumentation functions, but allow for debug printing
219%% of useful debug info.
220%%-----------------------------------------------------------------
221
222-spec dbg_apply(M :: atom(), F :: atom(), A :: list()) ->
223                       any().
224
225dbg_apply(M, F, A) ->
226    case get(verbosity) of
227	silence ->
228	    apply(M,F,A);
229	_ ->
230	    ?vlog("~n   apply: ~w, ~w, ~p~n", [M,F,A]),
231	    Res = (catch apply(M,F,A)),
232	    case Res of
233		{'EXIT', Reason} ->
234		    ?vinfo("Call to: "
235			   "~n   Module:   ~p"
236			   "~n   Function: ~p"
237			   "~n   Args:     ~p"
238			   "~n"
239			   "~nresulted in an exit"
240			   "~n"
241			   "~n   ~p~n", [M, F, A, Reason]);
242		_ ->
243		    ?vlog("~n   returned: ~p~n", [Res])
244	    end,
245	    Res
246    end.
247
248
249%% ---------------------------------------------------------------------
250
251user_err(F, A) ->
252    snmpa_error:user_err(F, A).
253
254
255