1 /*
2  * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.jmx.snmp.daemon;
27 
28 // java imports
29 //
30 import java.util.logging.Level;
31 import java.util.Vector;
32 
33 // jmx imports
34 //
35 import com.sun.jmx.snmp.SnmpEngine;
36 import com.sun.jmx.snmp.SnmpPdu;
37 import com.sun.jmx.snmp.SnmpValue;
38 import com.sun.jmx.snmp.SnmpVarBind;
39 import com.sun.jmx.snmp.SnmpVarBindList;
40 import com.sun.jmx.snmp.SnmpOid;
41 import com.sun.jmx.snmp.SnmpDefinitions;
42 import com.sun.jmx.snmp.SnmpStatusException;
43 // SNMP Runtime import
44 //
45 import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
46 import com.sun.jmx.snmp.agent.SnmpMibAgent;
47 import com.sun.jmx.snmp.agent.SnmpMibRequest;
48 import com.sun.jmx.snmp.daemon.SnmpAdaptorServer;
49 import com.sun.jmx.snmp.internal.SnmpIncomingRequest;
50 
51 /* NPCTE fix for bugId 4492741, esc 0 */
52 import com.sun.jmx.snmp.ThreadContext;
53 /* end of NPCTE fix for bugId 4492741 */
54 
55 class SnmpSubNextRequestHandler extends SnmpSubRequestHandler {
56     private SnmpAdaptorServer server = null;
57     /**
58      * The constructor initialize the subrequest with the whole varbind
59      * list contained in the original request.
60      */
SnmpSubNextRequestHandler(SnmpAdaptorServer server, SnmpMibAgent agent, SnmpPdu req)61     protected SnmpSubNextRequestHandler(SnmpAdaptorServer server,
62                                         SnmpMibAgent agent,
63                                         SnmpPdu req) {
64         super(agent,req);
65         init(req, server);
66     }
67 
SnmpSubNextRequestHandler(SnmpEngine engine, SnmpAdaptorServer server, SnmpIncomingRequest incRequest, SnmpMibAgent agent, SnmpPdu req)68     protected SnmpSubNextRequestHandler(SnmpEngine engine,
69                                         SnmpAdaptorServer server,
70                                         SnmpIncomingRequest incRequest,
71                                         SnmpMibAgent agent,
72                                         SnmpPdu req) {
73         super(engine, incRequest, agent, req);
74         init(req, server);
75         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
76             SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubNextRequestHandler.class.getName(),
77                 "SnmpSubNextRequestHandler", "Constructor : " + this);
78         }
79     }
80 
init(SnmpPdu req, SnmpAdaptorServer server)81     private void init(SnmpPdu req, SnmpAdaptorServer server) {
82         this.server = server;
83 
84         // The translation table is easy in this case ...
85         //
86         final int max= translation.length;
87         final SnmpVarBind[] list= req.varBindList;
88         final NonSyncVector<SnmpVarBind> nonSyncVarBind =
89                 ((NonSyncVector<SnmpVarBind>)varBind);
90         for(int i=0; i < max; i++) {
91             translation[i]= i;
92             // we need to allocate a new SnmpVarBind. Otherwise the first
93             // sub request will modify the list...
94             //
95             final SnmpVarBind newVarBind =
96                 new SnmpVarBind(list[i].oid, list[i].value);
97             nonSyncVarBind.addNonSyncElement(newVarBind);
98         }
99     }
100 
run()101     public void run() {
102 
103         try {
104             /* NPCTE fix for bugId 4492741, esc 0, 16-August-2001 */
105             final ThreadContext oldContext =
106                 ThreadContext.push("SnmpUserData",data);
107             try {
108                 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
109                     SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
110                         "run", "[" + Thread.currentThread() +
111                           "]:getNext operation on " + agent.getMibName());
112                 }
113 
114                 // Always call with V2. So the merge of the responses will
115                 // be easier.
116                 //
117                 agent.getNext(createMibRequest(varBind, snmpVersionTwo, data));
118             } finally {
119                 ThreadContext.restore(oldContext);
120             }
121             /* end of NPCTE fix for bugId 4492741 */
122 
123 
124         } catch(SnmpStatusException x) {
125             errorStatus = x.getStatus() ;
126             errorIndex=  x.getErrorIndex();
127             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
128                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
129                     "run", "[" + Thread.currentThread() +
130                       "]:an Snmp error occurred during the operation", x);
131             }
132         }
133         catch(Exception x) {
134             errorStatus = SnmpDefinitions.snmpRspGenErr ;
135             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
136                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
137                     "run", "[" + Thread.currentThread() +
138                       "]:a generic error occurred during the operation", x);
139             }
140         }
141         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
142             SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
143                 "run", "[" + Thread.currentThread() +  "]:operation completed");
144         }
145     }
146 
147     /**
148      * The method updates the varbind list of the subrequest.
149      */
updateRequest(SnmpVarBind var, int pos)150     protected  void updateRequest(SnmpVarBind var, int pos) {
151         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
152             SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
153                 "updateRequest", "Copy :" + var);
154         }
155         int size= varBind.size();
156         translation[size]= pos;
157         final SnmpVarBind newVarBind =
158             new SnmpVarBind(var.oid, var.value);
159         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
160             SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, SnmpSubRequestHandler.class.getName(),
161                 "updateRequest", "Copied :" + newVarBind);
162         }
163 
164         varBind.addElement(newVarBind);
165     }
166     /**
167      * The method updates a given var bind list with the result of a
168      * previsouly invoked operation.
169      * Prior to calling the method, one must make sure that the operation was
170      * successful. As such the method getErrorIndex or getErrorStatus should be
171      * called.
172      */
updateResult(SnmpVarBind[] result)173     protected void updateResult(SnmpVarBind[] result) {
174 
175         final int max=varBind.size();
176         for(int i= 0; i< max ; i++) {
177             // May be we should control the position ...
178             //
179             final int index= translation[i];
180             final SnmpVarBind elmt=
181                 (SnmpVarBind)((NonSyncVector)varBind).elementAtNonSync(i);
182 
183             final SnmpVarBind vb= result[index];
184             if (vb == null) {
185                 result[index]= elmt;
186                 /* NPCTE fix for bugid 4381195 esc 0. <J.C.> < 17-Oct-2000> */
187                 // if ((elmt != null) &&  (elmt.value == null) &&
188                 //    (version == snmpVersionTwo))
189                 //    elmt.value = SnmpVarBind.endOfMibView;
190                 /* end of NPCTE fix for bugid 4381195 */
191                 continue;
192             }
193 
194             final SnmpValue val= vb.value;
195             if ((val == null)|| (val == SnmpVarBind.endOfMibView)){
196                 /* NPCTE fix for bugid 4381195 esc 0. <J.C.> < 17-Oct-2000> */
197                 if ((elmt != null) &&
198                     (elmt.value != SnmpVarBind.endOfMibView))
199                     result[index]= elmt;
200                 // else if ((val == null) && (version == snmpVersionTwo))
201                 //    vb.value = SnmpVarBind.endOfMibView;
202                 continue;
203                 /* end of NPCTE fix for bugid 4381195 */
204             }
205 
206             /* NPCTE fix for bugid 4381195 esc 0. <J.C.> < 17-Oct-2000> */
207             if (elmt == null) continue;
208             /* end of NPCTE fix for bugid 4381195 */
209 
210             if (elmt.value == SnmpVarBind.endOfMibView) continue;
211 
212 
213             // Now we need to take the smallest oid ...
214             //
215             int comp = elmt.oid.compareTo(vb.oid);
216             if (comp < 0) {
217               // Take the smallest (lexicographically)
218                 //
219                 result[index]= elmt;
220             }
221             else {
222                 if(comp == 0) {
223                     // Must compare agent used for reply
224                     // Take the deeper within the reply
225                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
226                         SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
227                             "updateResult"," oid overlapping. Oid : " +
228                               elmt.oid + "value :" + elmt.value);
229                         SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
230                             "updateResult","Already present varBind : " +
231                               vb);
232                     }
233 
234                     SnmpOid oid = vb.oid;
235                     SnmpMibAgent deeperAgent = server.getAgentMib(oid);
236 
237                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
238                         SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
239                             "updateResult","Deeper agent : " + deeperAgent);
240                     }
241                     if(deeperAgent == agent) {
242                         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
243                             SNMP_ADAPTOR_LOGGER.logp(Level.FINER, SnmpSubRequestHandler.class.getName(),
244                                 "updateResult","The current agent is the deeper one. Update the value with the current one");
245                         }
246                         result[index].value = elmt.value;
247                     }
248 
249                     /*
250                       Vector v = new Vector();
251                       SnmpMibRequest getReq = createMibRequest(v,
252                       version,
253                       null);
254                       SnmpVarBind realValue = new SnmpVarBind(oid);
255                       getReq.addVarBind(realValue);
256                       try {
257                       deeperAgent.get(getReq);
258                       } catch(SnmpStatusException e) {
259                       e.printStackTrace();
260                       }
261 
262                       if(isDebugOn())
263                       trace("updateResult", "Biggest priority value is : " +
264                       realValue.value);
265 
266                       result[index].value = realValue.value;
267                     */
268                 }
269             }
270         }
271     }
272 }
273