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      */
  61     protected SnmpSubNextRequestHandler(SnmpAdaptorServer server,
  62                                         SnmpMibAgent agent,
  63                                         SnmpPdu req) {
  64         super(agent,req);
  65         init(req, server);
  66     }
  67 
  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 
  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 
 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      */
 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      */
 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 }