jdk/src/jdk.snmp/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java
changeset 27193 db6241373358
parent 27175 2c33a5c73a2e
parent 27192 a16236cd61d7
child 27194 48c1741d0f2a
equal deleted inserted replaced
27175:2c33a5c73a2e 27193:db6241373358
     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 
       
    27 package com.sun.jmx.snmp.daemon;
       
    28 
       
    29 
       
    30 
       
    31 // java import
       
    32 //
       
    33 import java.util.Vector;
       
    34 import java.util.Enumeration;
       
    35 import java.util.Hashtable;
       
    36 import java.util.logging.Level;
       
    37 import java.io.InterruptedIOException;
       
    38 import java.net.DatagramSocket;
       
    39 import java.net.DatagramPacket;
       
    40 import java.net.SocketException;
       
    41 
       
    42 // jmx imports
       
    43 //
       
    44 import javax.management.MBeanServer;
       
    45 import javax.management.ObjectName;
       
    46 import com.sun.jmx.snmp.SnmpMessage;
       
    47 import com.sun.jmx.snmp.SnmpPduFactory;
       
    48 import com.sun.jmx.snmp.SnmpPduBulk;
       
    49 import com.sun.jmx.snmp.SnmpPduPacket;
       
    50 import com.sun.jmx.snmp.SnmpPduRequest;
       
    51 import com.sun.jmx.snmp.SnmpPduTrap;
       
    52 import com.sun.jmx.snmp.SnmpValue;
       
    53 import com.sun.jmx.snmp.SnmpVarBind;
       
    54 import com.sun.jmx.snmp.SnmpVarBindList;
       
    55 import com.sun.jmx.snmp.SnmpDefinitions;
       
    56 import com.sun.jmx.snmp.SnmpStatusException;
       
    57 import com.sun.jmx.snmp.SnmpTooBigException;
       
    58 import com.sun.jmx.snmp.SnmpDataTypeEnums;
       
    59 
       
    60 // RI imports
       
    61 //
       
    62 import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;
       
    63 
       
    64 // SNMP runtime import
       
    65 //
       
    66 import com.sun.jmx.snmp.agent.SnmpMibAgent;
       
    67 import com.sun.jmx.snmp.agent.SnmpUserDataFactory;
       
    68 //import com.sun.jmx.snmp.IPAcl.IPAcl;
       
    69 import com.sun.jmx.snmp.InetAddressAcl;
       
    70 
       
    71 
       
    72 class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions {
       
    73 
       
    74     private transient DatagramSocket       socket = null ;
       
    75     private transient DatagramPacket       packet = null ;
       
    76     private transient Vector<SnmpMibAgent> mibs = null ;
       
    77 
       
    78     /**
       
    79      * Contains the list of sub-requests associated to the current request.
       
    80      */
       
    81     private transient Hashtable<SnmpMibAgent, SnmpSubRequestHandler> subs = null;
       
    82 
       
    83     /**
       
    84      * Reference on the MIBS
       
    85      */
       
    86     private transient SnmpMibTree root;
       
    87 
       
    88     private transient InetAddressAcl      ipacl = null ;
       
    89     private transient SnmpPduFactory      pduFactory = null ;
       
    90     private transient SnmpUserDataFactory userDataFactory = null ;
       
    91     private transient SnmpAdaptorServer adaptor = null;
       
    92     /**
       
    93      * Full constructor
       
    94      */
       
    95     public SnmpRequestHandler(SnmpAdaptorServer server, int id,
       
    96                               DatagramSocket s, DatagramPacket p,
       
    97                               SnmpMibTree tree, Vector<SnmpMibAgent> m,
       
    98                               InetAddressAcl a,
       
    99                               SnmpPduFactory factory,
       
   100                               SnmpUserDataFactory dataFactory,
       
   101                               MBeanServer f, ObjectName n)
       
   102     {
       
   103         super(server, id, f, n);
       
   104 
       
   105         // Need a reference on SnmpAdaptorServer for getNext & getBulk,
       
   106         // in case of oid equality (mib overlapping).
       
   107         //
       
   108         adaptor = server;
       
   109         socket = s;
       
   110         packet = p;
       
   111         root= tree;
       
   112         mibs = new Vector<>(m);
       
   113         subs= new Hashtable<>(mibs.size());
       
   114         ipacl = a;
       
   115         pduFactory = factory ;
       
   116         userDataFactory = dataFactory ;
       
   117         //thread.start();
       
   118     }
       
   119 
       
   120     /**
       
   121      * Treat the request available in 'packet' and send the result
       
   122      * back to the client.
       
   123      * Note: we overwrite 'packet' with the response bytes.
       
   124      */
       
   125     @Override
       
   126     public void doRun() {
       
   127 
       
   128         // Trace the input packet
       
   129         //
       
   130         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
       
   131             SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
   132                     "doRun","Packet received:\n" +
       
   133                     SnmpMessage.dumpHexBuffer(packet.getData(), 0, packet.getLength()));
       
   134         }
       
   135 
       
   136         // Let's build the response packet
       
   137         //
       
   138         DatagramPacket respPacket = makeResponsePacket(packet) ;
       
   139 
       
   140         // Trace the output packet
       
   141         //
       
   142         if ((SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) && (respPacket != null)) {
       
   143             SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
   144                     "doRun","Packet to be sent:\n" +
       
   145                     SnmpMessage.dumpHexBuffer(respPacket.getData(), 0, respPacket.getLength()));
       
   146         }
       
   147 
       
   148         // Send the response packet if any
       
   149         //
       
   150         if (respPacket != null) {
       
   151             try {
       
   152                 socket.send(respPacket) ;
       
   153             } catch (SocketException e) {
       
   154                 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   155                     if (e.getMessage().equals(InterruptSysCallMsg)) {
       
   156                         SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   157                             "doRun", "interrupted");
       
   158                     } else {
       
   159                       SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   160                             "doRun", "I/O exception", e);
       
   161                     }
       
   162                 }
       
   163             } catch(InterruptedIOException e) {
       
   164                 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   165                     SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   166                         "doRun", "interrupted");
       
   167                 }
       
   168             } catch(Exception e) {
       
   169                 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   170                     SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   171                         "doRun", "failure when sending response", e);
       
   172                 }
       
   173             }
       
   174         }
       
   175     }
       
   176 
       
   177     /**
       
   178      * Here we make a response packet from a request packet.
       
   179      * We return null if there no response packet to sent.
       
   180      */
       
   181     private DatagramPacket makeResponsePacket(DatagramPacket reqPacket) {
       
   182         DatagramPacket respPacket = null ;
       
   183 
       
   184         // Transform the request packet into a request SnmpMessage
       
   185         //
       
   186         SnmpMessage reqMsg = new SnmpMessage() ;
       
   187         try {
       
   188             reqMsg.decodeMessage(reqPacket.getData(), reqPacket.getLength()) ;
       
   189             reqMsg.address = reqPacket.getAddress() ;
       
   190             reqMsg.port = reqPacket.getPort() ;
       
   191         }
       
   192         catch(SnmpStatusException x) {
       
   193             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   194                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   195                     "makeResponsePacket", "packet decoding failed", x);
       
   196             }
       
   197             reqMsg = null ;
       
   198             ((SnmpAdaptorServer)adaptorServer).incSnmpInASNParseErrs(1) ;
       
   199         }
       
   200 
       
   201         // Make the response SnmpMessage if any
       
   202         //
       
   203         SnmpMessage respMsg = null ;
       
   204         if (reqMsg != null) {
       
   205             respMsg = makeResponseMessage(reqMsg) ;
       
   206         }
       
   207 
       
   208         // Try to transform the response SnmpMessage into response packet.
       
   209         // NOTE: we overwrite the request packet.
       
   210         //
       
   211         if (respMsg != null) {
       
   212             try {
       
   213                 reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ;
       
   214                 respPacket = reqPacket ;
       
   215             }
       
   216             catch(SnmpTooBigException x) {
       
   217                 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   218                     SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   219                         "makeResponsePacket", "response message is too big");
       
   220                 }
       
   221                 try {
       
   222                     respMsg = newTooBigMessage(reqMsg) ;
       
   223                     reqPacket.setLength(respMsg.encodeMessage(reqPacket.getData())) ;
       
   224                     respPacket = reqPacket ;
       
   225                 }
       
   226                 catch(SnmpTooBigException xx) {
       
   227                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   228                         SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   229                             "makeResponsePacket", "'too big' is 'too big' !!!");
       
   230                     }
       
   231                     adaptor.incSnmpSilentDrops(1);
       
   232                 }
       
   233             }
       
   234         }
       
   235 
       
   236         return respPacket ;
       
   237     }
       
   238 
       
   239     /**
       
   240      * Here we make a response message from a request message.
       
   241      * We return null if there is no message to reply.
       
   242      */
       
   243     private SnmpMessage makeResponseMessage(SnmpMessage reqMsg) {
       
   244         SnmpMessage respMsg = null ;
       
   245 
       
   246         // Transform the request message into a request pdu
       
   247         //
       
   248         SnmpPduPacket reqPdu;
       
   249         Object userData = null;
       
   250         try {
       
   251             reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ;
       
   252             if (reqPdu != null && userDataFactory != null)
       
   253                 userData = userDataFactory.allocateUserData(reqPdu);
       
   254         }
       
   255         catch(SnmpStatusException x) {
       
   256             reqPdu = null ;
       
   257             SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ;
       
   258             snmpServer.incSnmpInASNParseErrs(1) ;
       
   259             if (x.getStatus()== SnmpDefinitions.snmpWrongSnmpVersion)
       
   260                 snmpServer.incSnmpInBadVersions(1) ;
       
   261             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   262                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   263                     "makeResponseMessage", "message decoding failed", x);
       
   264             }
       
   265         }
       
   266 
       
   267         // Make the response pdu if any
       
   268         //
       
   269         SnmpPduPacket respPdu = null ;
       
   270         if (reqPdu != null) {
       
   271             respPdu = makeResponsePdu(reqPdu,userData) ;
       
   272             try {
       
   273                 if (userDataFactory != null)
       
   274                     userDataFactory.releaseUserData(userData,respPdu);
       
   275             } catch (SnmpStatusException x) {
       
   276                 respPdu = null;
       
   277             }
       
   278         }
       
   279 
       
   280         // Try to transform the response pdu into a response message if any
       
   281         //
       
   282         if (respPdu != null) {
       
   283             try {
       
   284                 respMsg = (SnmpMessage)pduFactory.
       
   285                     encodeSnmpPdu(respPdu, packet.getData().length) ;
       
   286             }
       
   287             catch(SnmpStatusException x) {
       
   288                 respMsg = null ;
       
   289                 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   290                     SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   291                         "makeResponseMessage", "failure when encoding the response message", x);
       
   292                 }
       
   293             }
       
   294             catch(SnmpTooBigException x) {
       
   295                 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   296                     SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   297                         "makeResponseMessage", "response message is too big");
       
   298                 }
       
   299 
       
   300                 try {
       
   301                     // if the PDU is too small, why should we try to do
       
   302                     // recovery ?
       
   303                     //
       
   304                     if (packet.getData().length <=32)
       
   305                         throw x;
       
   306                     int pos= x.getVarBindCount();
       
   307                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   308                         SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   309                             "makeResponseMessage", "fail on element" + pos);
       
   310                     }
       
   311                     int old;
       
   312                     while (true) {
       
   313                         try {
       
   314                             respPdu = reduceResponsePdu(reqPdu, respPdu, pos) ;
       
   315                             respMsg = (SnmpMessage)pduFactory.
       
   316                                 encodeSnmpPdu(respPdu,
       
   317                                               packet.getData().length -32) ;
       
   318                             break;
       
   319                         } catch (SnmpTooBigException xx) {
       
   320                             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   321                                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   322                                     "makeResponseMessage", "response message is still too big");
       
   323                             }
       
   324                             old= pos;
       
   325                             pos= xx.getVarBindCount();
       
   326                             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   327                                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   328                                     "makeResponseMessage","fail on element" + pos);
       
   329                             }
       
   330                             if (pos == old) {
       
   331                                 // we can not go any further in trying to
       
   332                                 // reduce the message !
       
   333                                 //
       
   334                                 throw xx;
       
   335                             }
       
   336                         }
       
   337                     }// end of loop
       
   338                 } catch(SnmpStatusException xx) {
       
   339                     respMsg = null ;
       
   340                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   341                         SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   342                            "makeResponseMessage", "failure when encoding the response message", xx);
       
   343                     }
       
   344                 }
       
   345                 catch(SnmpTooBigException xx) {
       
   346                     try {
       
   347                         respPdu = newTooBigPdu(reqPdu) ;
       
   348                         respMsg = (SnmpMessage)pduFactory.
       
   349                             encodeSnmpPdu(respPdu, packet.getData().length) ;
       
   350                     }
       
   351                     catch(SnmpTooBigException xxx) {
       
   352                         respMsg = null ;
       
   353                         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   354                             SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   355                                "makeResponseMessage", "'too big' is 'too big' !!!");
       
   356                         }
       
   357                         adaptor.incSnmpSilentDrops(1);
       
   358                     }
       
   359                     catch(Exception xxx) {
       
   360                         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   361                             SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   362                                "makeResponseMessage", "Got unexpected exception", xxx);
       
   363                         }
       
   364                         respMsg = null ;
       
   365                     }
       
   366                 }
       
   367                 catch(Exception xx) {
       
   368                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   369                         SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   370                            "makeResponseMessage", "Got unexpected exception", xx);
       
   371                     }
       
   372                     respMsg = null ;
       
   373                 }
       
   374             }
       
   375         }
       
   376         return respMsg ;
       
   377     }
       
   378 
       
   379     /**
       
   380      * Here we make a response pdu from a request pdu.
       
   381      * We return null if there is no pdu to reply.
       
   382      */
       
   383     private SnmpPduPacket makeResponsePdu(SnmpPduPacket reqPdu,
       
   384                                           Object userData) {
       
   385 
       
   386         SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ;
       
   387         SnmpPduPacket respPdu = null ;
       
   388 
       
   389         snmpServer.updateRequestCounters(reqPdu.type) ;
       
   390         if (reqPdu.varBindList != null)
       
   391             snmpServer.updateVarCounters(reqPdu.type,
       
   392                                          reqPdu.varBindList.length) ;
       
   393 
       
   394         if (checkPduType(reqPdu)) {
       
   395             respPdu = checkAcl(reqPdu) ;
       
   396             if (respPdu == null) { // reqPdu is accepted by ACLs
       
   397                 if (mibs.size() < 1) {
       
   398                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
       
   399                         SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
   400                            "makeResponsePdu", "Request " + reqPdu.requestId +
       
   401                            " received but no MIB registered.");
       
   402                     }
       
   403                     return makeNoMibErrorPdu((SnmpPduRequest)reqPdu, userData);
       
   404                 }
       
   405                 switch(reqPdu.type) {
       
   406                 case SnmpPduPacket.pduGetRequestPdu:
       
   407                 case SnmpPduPacket.pduGetNextRequestPdu:
       
   408                 case SnmpPduPacket.pduSetRequestPdu:
       
   409                     respPdu = makeGetSetResponsePdu((SnmpPduRequest)reqPdu,
       
   410                                                     userData) ;
       
   411                     break ;
       
   412 
       
   413                 case SnmpPduPacket.pduGetBulkRequestPdu:
       
   414                     respPdu = makeGetBulkResponsePdu((SnmpPduBulk)reqPdu,
       
   415                                                      userData) ;
       
   416                     break ;
       
   417                 }
       
   418             }
       
   419             else { // reqPdu is rejected by ACLs
       
   420                 // respPdu contains the error response to be sent.
       
   421                 // We send this response only if authResEnabled is true.
       
   422                 if (!snmpServer.getAuthRespEnabled()) { // No response should be sent
       
   423                     respPdu = null ;
       
   424                 }
       
   425                 if (snmpServer.getAuthTrapEnabled()) { // A trap must be sent
       
   426                     try {
       
   427                         snmpServer.snmpV1Trap(SnmpPduTrap.
       
   428                                               trapAuthenticationFailure, 0,
       
   429                                               new SnmpVarBindList()) ;
       
   430                     }
       
   431                     catch(Exception x) {
       
   432                         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   433                             SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   434                                "makeResponsePdu", "Failure when sending authentication trap", x);
       
   435                         }
       
   436                     }
       
   437                 }
       
   438             }
       
   439         }
       
   440         return respPdu ;
       
   441     }
       
   442 
       
   443     //
       
   444     // Generates a response packet, filling the values in the
       
   445     // varbindlist with one of endOfMibView, noSuchObject, noSuchInstance
       
   446     // according to the value of <code>status</code>
       
   447     //
       
   448     // @param statusTag should be one of:
       
   449     //        <li>SnmpDataTypeEnums.errEndOfMibViewTag</li>
       
   450     //        <li>SnmpDataTypeEnums.errNoSuchObjectTag</li>
       
   451     //        <li>SnmpDataTypeEnums.errNoSuchInstanceTag</li>
       
   452     //
       
   453     SnmpPduPacket makeErrorVarbindPdu(SnmpPduPacket req, int statusTag) {
       
   454 
       
   455         final SnmpVarBind[] vblist = req.varBindList;
       
   456         final int length = vblist.length;
       
   457 
       
   458         switch (statusTag) {
       
   459         case SnmpDataTypeEnums.errEndOfMibViewTag:
       
   460             for (int i=0 ; i<length ; i++)
       
   461                 vblist[i].value = SnmpVarBind.endOfMibView;
       
   462             break;
       
   463         case SnmpDataTypeEnums.errNoSuchObjectTag:
       
   464             for (int i=0 ; i<length ; i++)
       
   465                 vblist[i].value = SnmpVarBind.noSuchObject;
       
   466             break;
       
   467         case SnmpDataTypeEnums.errNoSuchInstanceTag:
       
   468             for (int i=0 ; i<length ; i++)
       
   469                 vblist[i].value = SnmpVarBind.noSuchInstance;
       
   470             break;
       
   471         default:
       
   472             return newErrorResponsePdu(req,snmpRspGenErr,1);
       
   473         }
       
   474         return newValidResponsePdu(req,vblist);
       
   475     }
       
   476 
       
   477     // Generates an appropriate response when no mib is registered in
       
   478     // the adaptor.
       
   479     //
       
   480     // <li>If the version is V1:</li>
       
   481     // <ul><li>Generates a NoSuchName error V1 response PDU</li></ul>
       
   482     // <li>If the version is V2:</li>
       
   483     // <ul><li>If the request is a GET, fills the varbind list with
       
   484     //         NoSuchObject's</li>
       
   485     //     <li>If the request is a GET-NEXT/GET-BULK, fills the varbind
       
   486     //         list with EndOfMibView's</li>
       
   487     //     <li>If the request is a SET, generates a NoAccess error V2
       
   488     //          response PDU</li>
       
   489     // </ul>
       
   490     //
       
   491     //
       
   492     SnmpPduPacket makeNoMibErrorPdu(SnmpPduRequest req, Object userData) {
       
   493         // There is no agent registered
       
   494         //
       
   495         if (req.version == SnmpDefinitions.snmpVersionOne) {
       
   496             // Version 1: => NoSuchName
       
   497             return
       
   498                 newErrorResponsePdu(req,snmpRspNoSuchName,1);
       
   499         } else if (req.version == SnmpDefinitions.snmpVersionTwo) {
       
   500             // Version 2: => depends on PDU type
       
   501             switch (req.type) {
       
   502             case pduSetRequestPdu :
       
   503             case pduWalkRequest :
       
   504                 // SET request => NoAccess
       
   505                 return
       
   506                     newErrorResponsePdu(req,snmpRspNoAccess,1);
       
   507             case pduGetRequestPdu :
       
   508                 // GET request => NoSuchObject
       
   509                 return
       
   510                     makeErrorVarbindPdu(req,SnmpDataTypeEnums.
       
   511                                         errNoSuchObjectTag);
       
   512             case pduGetNextRequestPdu :
       
   513             case pduGetBulkRequestPdu :
       
   514                 // GET-NEXT or GET-BULK => EndOfMibView
       
   515                 return
       
   516                     makeErrorVarbindPdu(req,SnmpDataTypeEnums.
       
   517                                         errEndOfMibViewTag);
       
   518             default:
       
   519             }
       
   520         }
       
   521         // Something wrong here: => snmpRspGenErr
       
   522         return newErrorResponsePdu(req,snmpRspGenErr,1);
       
   523     }
       
   524 
       
   525     /**
       
   526      * Here we make the response pdu from a get/set request pdu.
       
   527      * At this level, the result is never null.
       
   528      */
       
   529     private SnmpPduPacket makeGetSetResponsePdu(SnmpPduRequest req,
       
   530                                                 Object userData) {
       
   531 
       
   532         // Create the trhead group specific for handling sub-requests
       
   533         // associated to the current request. Use the invoke id
       
   534         //
       
   535         // Nice idea to use a thread group on a request basis.
       
   536         // However the impact on performance is terrible !
       
   537         // theGroup= new ThreadGroup(thread.getThreadGroup(),
       
   538         //                "request " + String.valueOf(req.requestId));
       
   539 
       
   540         // Let's build the varBindList for the response pdu
       
   541         //
       
   542 
       
   543         if (req.varBindList == null) {
       
   544             // Good ! Let's make a full response pdu.
       
   545             //
       
   546             return newValidResponsePdu(req, null) ;
       
   547         }
       
   548 
       
   549         // First we need to split the request into subrequests
       
   550         //
       
   551         splitRequest(req);
       
   552         int nbSubRequest= subs.size();
       
   553         if (nbSubRequest == 1)
       
   554             return turboProcessingGetSet(req,userData);
       
   555 
       
   556 
       
   557         // Execute all the subrequests resulting from the split of the
       
   558         // varbind list.
       
   559         //
       
   560         SnmpPduPacket result= executeSubRequest(req,userData);
       
   561         if (result != null)
       
   562             // It means that an error occurred. The error is already
       
   563             // formatted by the executeSubRequest
       
   564             // method.
       
   565             return result;
       
   566 
       
   567         // So far so good. So we need to concatenate all the answers.
       
   568         //
       
   569         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
       
   570             SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
   571                "makeGetSetResponsePdu",
       
   572                "Build the unified response for request " + req.requestId);
       
   573         }
       
   574         return mergeResponses(req);
       
   575     }
       
   576 
       
   577     /**
       
   578      * The method runs all the sub-requests associated to the current
       
   579      * instance of SnmpRequestHandler.
       
   580      */
       
   581     private SnmpPduPacket executeSubRequest(SnmpPduPacket req,
       
   582                                             Object userData) {
       
   583 
       
   584         int errorStatus = SnmpDefinitions.snmpRspNoError ;
       
   585 
       
   586         int i;
       
   587         // If it's a set request, we must first check any varBind
       
   588         //
       
   589         if (req.type == pduSetRequestPdu) {
       
   590 
       
   591             i=0;
       
   592             for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements() ; i++) {
       
   593                 // Indicate to the sub request that a check must be invoked ...
       
   594                 // OK we should have defined out own tag for that !
       
   595                 //
       
   596                 SnmpSubRequestHandler sub= e.nextElement();
       
   597                 sub.setUserData(userData);
       
   598                 sub.type= pduWalkRequest;
       
   599 
       
   600                 sub.run();
       
   601 
       
   602                 sub.type= pduSetRequestPdu;
       
   603 
       
   604                 if (sub.getErrorStatus() != SnmpDefinitions.snmpRspNoError) {
       
   605                     // No point to go any further.
       
   606                     //
       
   607                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   608                         SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   609                            "executeSubRequest", "an error occurs");
       
   610                     }
       
   611 
       
   612                     return newErrorResponsePdu(req, errorStatus,
       
   613                                                sub.getErrorIndex() + 1) ;
       
   614                 }
       
   615             }
       
   616         }// end processing check operation for a set PDU.
       
   617 
       
   618         // Let's start the sub-requests.
       
   619         //
       
   620         i=0;
       
   621         for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements() ;i++) {
       
   622             SnmpSubRequestHandler sub= e.nextElement();
       
   623         /* NPCTE fix for bugId 4492741, esc 0, 16-August 2001 */
       
   624             sub.setUserData(userData);
       
   625         /* end of NPCTE fix for bugId 4492741 */
       
   626 
       
   627             sub.run();
       
   628 
       
   629             if (sub.getErrorStatus() != SnmpDefinitions.snmpRspNoError) {
       
   630                 // No point to go any further.
       
   631                 //
       
   632                 if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   633                     SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   634                        "executeSubRequest", "an error occurs");
       
   635                 }
       
   636 
       
   637                 return newErrorResponsePdu(req, errorStatus,
       
   638                                            sub.getErrorIndex() + 1) ;
       
   639             }
       
   640         }
       
   641 
       
   642         // everything is ok
       
   643         //
       
   644         return null;
       
   645     }
       
   646 
       
   647     /**
       
   648      * Optimize when there is only one sub request
       
   649      */
       
   650     private SnmpPduPacket turboProcessingGetSet(SnmpPduRequest req,
       
   651                                                 Object userData) {
       
   652 
       
   653         int errorStatus;
       
   654         SnmpSubRequestHandler sub = subs.elements().nextElement();
       
   655         sub.setUserData(userData);
       
   656 
       
   657         // Indicate to the sub request that a check must be invoked ...
       
   658         // OK we should have defined out own tag for that !
       
   659         //
       
   660         if (req.type == SnmpDefinitions.pduSetRequestPdu) {
       
   661             sub.type= pduWalkRequest;
       
   662             sub.run();
       
   663             sub.type= pduSetRequestPdu;
       
   664 
       
   665             // Check the error status.
       
   666             //
       
   667             errorStatus= sub.getErrorStatus();
       
   668             if (errorStatus != SnmpDefinitions.snmpRspNoError) {
       
   669                 // No point to go any further.
       
   670                 //
       
   671                 return newErrorResponsePdu(req, errorStatus,
       
   672                                            sub.getErrorIndex() + 1) ;
       
   673             }
       
   674         }
       
   675 
       
   676         // process the operation
       
   677         //
       
   678 
       
   679         sub.run();
       
   680         errorStatus= sub.getErrorStatus();
       
   681         if (errorStatus != SnmpDefinitions.snmpRspNoError) {
       
   682             // No point to go any further.
       
   683             //
       
   684             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   685                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   686                    "turboProcessingGetSet", "an error occurs");
       
   687             }
       
   688             int realIndex= sub.getErrorIndex() + 1;
       
   689             return newErrorResponsePdu(req, errorStatus, realIndex) ;
       
   690         }
       
   691 
       
   692         // So far so good. So we need to concatenate all the answers.
       
   693         //
       
   694 
       
   695         if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
       
   696             SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
   697                "turboProcessingGetSet",  "build the unified response for request "
       
   698                 + req.requestId);
       
   699         }
       
   700         return mergeResponses(req);
       
   701     }
       
   702 
       
   703     /**
       
   704      * Here we make the response pdu for a bulk request.
       
   705      * At this level, the result is never null.
       
   706      */
       
   707     private SnmpPduPacket makeGetBulkResponsePdu(SnmpPduBulk req,
       
   708                                                  Object userData) {
       
   709 
       
   710         SnmpVarBind[] respVarBindList;
       
   711 
       
   712         // RFC 1905, Section 4.2.3, p14
       
   713         int L = req.varBindList.length ;
       
   714         int N = Math.max(Math.min(req.nonRepeaters, L), 0) ;
       
   715         int M = Math.max(req.maxRepetitions, 0) ;
       
   716         int R = L - N ;
       
   717 
       
   718         if (req.varBindList == null) {
       
   719             // Good ! Let's make a full response pdu.
       
   720             //
       
   721             return newValidResponsePdu(req, null) ;
       
   722         }
       
   723 
       
   724         // Split the request into subrequests.
       
   725         //
       
   726         splitBulkRequest(req, N, M, R);
       
   727         SnmpPduPacket result= executeSubRequest(req,userData);
       
   728         if (result != null)
       
   729             return result;
       
   730 
       
   731         respVarBindList= mergeBulkResponses(N + (M * R));
       
   732 
       
   733         // Now we remove useless trailing endOfMibView.
       
   734         //
       
   735         int m2 ; // respVarBindList[m2] item and next are going to be removed
       
   736         int t = respVarBindList.length ;
       
   737         while ((t > N) && (respVarBindList[t-1].
       
   738                            value.equals(SnmpVarBind.endOfMibView))) {
       
   739             t-- ;
       
   740         }
       
   741         if (t == N)
       
   742             m2 = N + R ;
       
   743         else
       
   744             m2 = N + ((t -1 -N) / R + 2) * R ; // Trivial, of course...
       
   745         if (m2 < respVarBindList.length) {
       
   746             SnmpVarBind[] truncatedList = new SnmpVarBind[m2] ;
       
   747             for (int i = 0 ; i < m2 ; i++) {
       
   748                 truncatedList[i] = respVarBindList[i] ;
       
   749             }
       
   750             respVarBindList = truncatedList ;
       
   751         }
       
   752 
       
   753         // Good ! Let's make a full response pdu.
       
   754         //
       
   755         return newValidResponsePdu(req, respVarBindList) ;
       
   756     }
       
   757 
       
   758     /**
       
   759      * Check the type of the pdu: only the get/set/bulk request
       
   760      * are accepted.
       
   761      */
       
   762     private boolean checkPduType(SnmpPduPacket pdu) {
       
   763 
       
   764         boolean result;
       
   765 
       
   766         switch(pdu.type) {
       
   767 
       
   768         case SnmpDefinitions.pduGetRequestPdu:
       
   769         case SnmpDefinitions.pduGetNextRequestPdu:
       
   770         case SnmpDefinitions.pduSetRequestPdu:
       
   771         case SnmpDefinitions.pduGetBulkRequestPdu:
       
   772             result = true ;
       
   773             break;
       
   774 
       
   775         default:
       
   776             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   777                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   778                    "checkPduType", "cannot respond to this kind of PDU");
       
   779             }
       
   780             result = false ;
       
   781             break;
       
   782         }
       
   783 
       
   784         return result ;
       
   785     }
       
   786 
       
   787     /**
       
   788      * Check if the specified pdu is conform to the ACL.
       
   789      * This method returns null if the pdu is ok. If not, it returns
       
   790      * the response pdu to be replied.
       
   791      */
       
   792     private SnmpPduPacket checkAcl(SnmpPduPacket pdu) {
       
   793         SnmpPduPacket response = null ;
       
   794         String community = new String(pdu.community) ;
       
   795 
       
   796         // We check the pdu type and create an error response if
       
   797         // the check failed.
       
   798         //
       
   799         if (ipacl != null) {
       
   800             if (pdu.type == SnmpDefinitions.pduSetRequestPdu) {
       
   801                 if (!ipacl.checkWritePermission(pdu.address, community)) {
       
   802                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
       
   803                         SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
   804                            "checkAcl", "sender is " + pdu.address +
       
   805                               " with " + community +". Sender has no write permission");
       
   806                     }
       
   807                     int err = SnmpSubRequestHandler.
       
   808                         mapErrorStatus(SnmpDefinitions.
       
   809                                        snmpRspAuthorizationError,
       
   810                                        pdu.version, pdu.type);
       
   811                     response = newErrorResponsePdu(pdu, err, 0) ;
       
   812                 }
       
   813                 else {
       
   814                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
       
   815                         SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
   816                            "checkAcl", "sender is " + pdu.address +
       
   817                               " with " + community +". Sender has write permission");
       
   818                     }
       
   819                 }
       
   820             }
       
   821             else {
       
   822                 if (!ipacl.checkReadPermission(pdu.address, community)) {
       
   823                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
       
   824                         SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
   825                            "checkAcl", "sender is " + pdu.address +
       
   826                               " with " + community +". Sender has no read permission");
       
   827                     }
       
   828                     int err = SnmpSubRequestHandler.
       
   829                         mapErrorStatus(SnmpDefinitions.
       
   830                                        snmpRspAuthorizationError,
       
   831                                        pdu.version, pdu.type);
       
   832                     response = newErrorResponsePdu(pdu,
       
   833                                                    err,
       
   834                                                    0);
       
   835                     SnmpAdaptorServer snmpServer =
       
   836                         (SnmpAdaptorServer)adaptorServer;
       
   837                     snmpServer.updateErrorCounters(SnmpDefinitions.
       
   838                                                    snmpRspNoSuchName);
       
   839                 }
       
   840                 else {
       
   841                     if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
       
   842                         SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
   843                            "checkAcl", "sender is " + pdu.address +
       
   844                               " with " + community +". Sender has read permission");
       
   845                     }
       
   846                 }
       
   847             }
       
   848         }
       
   849 
       
   850         // If the response is not null, this means the pdu is rejected.
       
   851         // So let's update the statistics.
       
   852         //
       
   853         if (response != null) {
       
   854             SnmpAdaptorServer snmpServer = (SnmpAdaptorServer)adaptorServer ;
       
   855             snmpServer.incSnmpInBadCommunityUses(1) ;
       
   856             if (ipacl.checkCommunity(community) == false)
       
   857                 snmpServer.incSnmpInBadCommunityNames(1) ;
       
   858         }
       
   859 
       
   860         return response ;
       
   861     }
       
   862 
       
   863     /**
       
   864      * Make a response pdu with the specified error status and index.
       
   865      * NOTE: the response pdu share its varBindList with the request pdu.
       
   866      */
       
   867     private SnmpPduRequest newValidResponsePdu(SnmpPduPacket reqPdu,
       
   868                                                SnmpVarBind[] varBindList) {
       
   869         SnmpPduRequest result = new SnmpPduRequest() ;
       
   870 
       
   871         result.address = reqPdu.address ;
       
   872         result.port = reqPdu.port ;
       
   873         result.version = reqPdu.version ;
       
   874         result.community = reqPdu.community ;
       
   875         result.type = SnmpPduRequest.pduGetResponsePdu ;
       
   876         result.requestId = reqPdu.requestId ;
       
   877         result.errorStatus = SnmpDefinitions.snmpRspNoError ;
       
   878         result.errorIndex = 0 ;
       
   879         result.varBindList = varBindList ;
       
   880 
       
   881         ((SnmpAdaptorServer)adaptorServer).
       
   882             updateErrorCounters(result.errorStatus) ;
       
   883 
       
   884         return result ;
       
   885     }
       
   886 
       
   887     /**
       
   888      * Make a response pdu with the specified error status and index.
       
   889      * NOTE: the response pdu share its varBindList with the request pdu.
       
   890      */
       
   891     private SnmpPduRequest newErrorResponsePdu(SnmpPduPacket req,int s,int i) {
       
   892         SnmpPduRequest result = newValidResponsePdu(req, null) ;
       
   893         result.errorStatus = s ;
       
   894         result.errorIndex = i ;
       
   895         result.varBindList = req.varBindList ;
       
   896 
       
   897         ((SnmpAdaptorServer)adaptorServer).
       
   898             updateErrorCounters(result.errorStatus) ;
       
   899 
       
   900         return result ;
       
   901     }
       
   902 
       
   903     private SnmpMessage newTooBigMessage(SnmpMessage reqMsg)
       
   904         throws SnmpTooBigException {
       
   905         SnmpMessage result = null ;
       
   906         SnmpPduPacket reqPdu;
       
   907 
       
   908         try {
       
   909             reqPdu = (SnmpPduPacket)pduFactory.decodeSnmpPdu(reqMsg) ;
       
   910             if (reqPdu != null) {
       
   911                 SnmpPduPacket respPdu = newTooBigPdu(reqPdu) ;
       
   912                 result = (SnmpMessage)pduFactory.
       
   913                     encodeSnmpPdu(respPdu, packet.getData().length) ;
       
   914             }
       
   915         }
       
   916         catch(SnmpStatusException x) {
       
   917             // This should not occur because decodeIncomingRequest has normally
       
   918             // been successfully called before.
       
   919             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   920                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   921                    "newTooBigMessage", "Internal error", x);
       
   922             }
       
   923             throw new InternalError(x) ;
       
   924         }
       
   925 
       
   926         return result ;
       
   927     }
       
   928 
       
   929     private SnmpPduPacket newTooBigPdu(SnmpPduPacket req) {
       
   930         SnmpPduRequest result =
       
   931             newErrorResponsePdu(req, SnmpDefinitions.snmpRspTooBig, 0) ;
       
   932         result.varBindList = null ;
       
   933         return result ;
       
   934     }
       
   935 
       
   936     private SnmpPduPacket reduceResponsePdu(SnmpPduPacket req,
       
   937                                             SnmpPduPacket resp,
       
   938                                             int acceptedVbCount)
       
   939         throws SnmpTooBigException {
       
   940 
       
   941         // Reduction can be attempted only on bulk response
       
   942         //
       
   943         if (req.type != SnmpPduPacket.pduGetBulkRequestPdu) {
       
   944             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   945                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   946                    "reduceResponsePdu", "cannot remove anything");
       
   947             }
       
   948             throw new SnmpTooBigException(acceptedVbCount) ;
       
   949         }
       
   950 
       
   951         // We're going to reduce the varbind list.
       
   952         // First determine which items should be removed.
       
   953         // Next duplicate and replace the existing list by the reduced one.
       
   954         //
       
   955         // acceptedVbCount is the number of varbind which have been
       
   956         // successfully encoded before reaching bufferSize:
       
   957         //   * when it is >= 2, we split the varbindlist at this
       
   958         //     position (-1 to be safe),
       
   959         //   * when it is 1, we only put one (big?) item in the varbindlist
       
   960         //   * when it is 0 (in fact, acceptedVbCount is not available),
       
   961         //     we split the varbindlist by 2.
       
   962         //
       
   963         int vbCount;
       
   964         if (acceptedVbCount >= 3)
       
   965             vbCount = Math.min(acceptedVbCount - 1, resp.varBindList.length) ;
       
   966         else if (acceptedVbCount == 1)
       
   967             vbCount = 1 ;
       
   968         else // acceptedCount == 0 ie it is unknown
       
   969             vbCount = resp.varBindList.length / 2 ;
       
   970 
       
   971         if (vbCount < 1) {
       
   972             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   973                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   974                    "reduceResponsePdu", "cannot remove anything");
       
   975             }
       
   976             throw new SnmpTooBigException(acceptedVbCount) ;
       
   977         }
       
   978         else {
       
   979             SnmpVarBind[] newVbList = new SnmpVarBind[vbCount] ;
       
   980             for (int i = 0 ; i < vbCount ; i++) {
       
   981                 newVbList[i] = resp.varBindList[i] ;
       
   982             }
       
   983             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) {
       
   984                 SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag,
       
   985                    "reduceResponsePdu", (resp.varBindList.length - newVbList.length) +
       
   986                     " items have been removed");
       
   987             }
       
   988             resp.varBindList = newVbList ;
       
   989         }
       
   990 
       
   991         return resp ;
       
   992     }
       
   993 
       
   994     /**
       
   995      * The method takes the incoming requests and split it into subrequests.
       
   996      */
       
   997     private void splitRequest(SnmpPduRequest req) {
       
   998 
       
   999         int nbAgents= mibs.size();
       
  1000         SnmpMibAgent agent = mibs.firstElement();
       
  1001         if (nbAgents == 1) {
       
  1002             // Take all the oids contained in the request and
       
  1003             //
       
  1004             subs.put(agent, new SnmpSubRequestHandler(agent, req, true));
       
  1005             return;
       
  1006         }
       
  1007 
       
  1008         // For the get next operation we are going to send the varbind list
       
  1009         // to all agents
       
  1010         //
       
  1011         if (req.type == pduGetNextRequestPdu) {
       
  1012             for(Enumeration<SnmpMibAgent> e= mibs.elements(); e.hasMoreElements(); ) {
       
  1013                 final SnmpMibAgent ag= e.nextElement();
       
  1014                 subs.put(ag, new SnmpSubNextRequestHandler(adaptor, ag, req));
       
  1015             }
       
  1016             return;
       
  1017         }
       
  1018 
       
  1019         int nbReqs= req.varBindList.length;
       
  1020         SnmpVarBind[] vars= req.varBindList;
       
  1021         SnmpSubRequestHandler sub;
       
  1022         for(int i=0; i < nbReqs; i++) {
       
  1023             agent= root.getAgentMib(vars[i].oid);
       
  1024             sub= subs.get(agent);
       
  1025             if (sub == null) {
       
  1026                 // We need to create the sub request handler and update
       
  1027                 // the hashtable
       
  1028                 //
       
  1029                 sub= new SnmpSubRequestHandler(agent, req);
       
  1030                 subs.put(agent, sub);
       
  1031             }
       
  1032 
       
  1033             // Update the translation table within the subrequest
       
  1034             //
       
  1035             sub.updateRequest(vars[i], i);
       
  1036         }
       
  1037     }
       
  1038 
       
  1039     /**
       
  1040      * The method takes the incoming get bulk requests and split it into
       
  1041      * subrequests.
       
  1042      */
       
  1043     private void splitBulkRequest(SnmpPduBulk req,
       
  1044                                   int nonRepeaters,
       
  1045                                   int maxRepetitions,
       
  1046                                   int R) {
       
  1047         // Send the getBulk to all agents
       
  1048         //
       
  1049         for(Enumeration<SnmpMibAgent> e= mibs.elements(); e.hasMoreElements(); ) {
       
  1050             final SnmpMibAgent agent = e.nextElement();
       
  1051 
       
  1052             if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) {
       
  1053                 SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag,
       
  1054                    "splitBulkRequest", "Create a sub with : " + agent + " " + nonRepeaters
       
  1055                    + " " + maxRepetitions + " " + R);
       
  1056             }
       
  1057 
       
  1058             subs.put(agent,
       
  1059                      new SnmpSubBulkRequestHandler(adaptor,
       
  1060                                                    agent,
       
  1061                                                    req,
       
  1062                                                    nonRepeaters,
       
  1063                                                    maxRepetitions,
       
  1064                                                    R));
       
  1065         }
       
  1066     }
       
  1067 
       
  1068     private SnmpPduPacket mergeResponses(SnmpPduRequest req) {
       
  1069 
       
  1070         if (req.type == pduGetNextRequestPdu) {
       
  1071             return mergeNextResponses(req);
       
  1072         }
       
  1073 
       
  1074         SnmpVarBind[] result= req.varBindList;
       
  1075 
       
  1076         // Go through the list of subrequests and concatenate.
       
  1077         // Hopefully, by now all the sub-requests should be finished
       
  1078         //
       
  1079         for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements();) {
       
  1080             SnmpSubRequestHandler sub= e.nextElement();
       
  1081             sub.updateResult(result);
       
  1082         }
       
  1083         return newValidResponsePdu(req,result);
       
  1084     }
       
  1085 
       
  1086     private SnmpPduPacket mergeNextResponses(SnmpPduRequest req) {
       
  1087         int max= req.varBindList.length;
       
  1088         SnmpVarBind[] result= new SnmpVarBind[max];
       
  1089 
       
  1090         // Go through the list of subrequests and concatenate.
       
  1091         // Hopefully, by now all the sub-requests should be finished
       
  1092         //
       
  1093         for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements();) {
       
  1094             SnmpSubRequestHandler sub= e.nextElement();
       
  1095             sub.updateResult(result);
       
  1096         }
       
  1097 
       
  1098         if (req.version == snmpVersionTwo) {
       
  1099             return newValidResponsePdu(req,result);
       
  1100         }
       
  1101 
       
  1102         // In v1 make sure there is no endOfMibView ...
       
  1103         //
       
  1104         for(int i=0; i < max; i++) {
       
  1105             SnmpValue val= result[i].value;
       
  1106             if (val == SnmpVarBind.endOfMibView)
       
  1107                 return newErrorResponsePdu(req,
       
  1108                                    SnmpDefinitions.snmpRspNoSuchName, i+1);
       
  1109         }
       
  1110 
       
  1111         // So far so good ...
       
  1112         //
       
  1113         return newValidResponsePdu(req,result);
       
  1114     }
       
  1115 
       
  1116     private SnmpVarBind[] mergeBulkResponses(int size) {
       
  1117         // Let's allocate the array for storing the result
       
  1118         //
       
  1119         SnmpVarBind[] result= new SnmpVarBind[size];
       
  1120         for(int i= size-1; i >=0; --i) {
       
  1121             result[i]= new SnmpVarBind();
       
  1122             result[i].value= SnmpVarBind.endOfMibView;
       
  1123         }
       
  1124 
       
  1125         // Go through the list of subrequests and concatenate.
       
  1126         // Hopefully, by now all the sub-requests should be finished
       
  1127         //
       
  1128         for(Enumeration<SnmpSubRequestHandler> e= subs.elements(); e.hasMoreElements();) {
       
  1129             SnmpSubRequestHandler sub= e.nextElement();
       
  1130             sub.updateResult(result);
       
  1131         }
       
  1132 
       
  1133         return result;
       
  1134     }
       
  1135 
       
  1136     @Override
       
  1137     protected String makeDebugTag() {
       
  1138         return "SnmpRequestHandler[" + adaptorServer.getProtocol() + ":" +
       
  1139             adaptorServer.getPort() + "]";
       
  1140     }
       
  1141 
       
  1142     @Override
       
  1143     Thread createThread(Runnable r) {
       
  1144         return null;
       
  1145     }
       
  1146 
       
  1147     static final private String InterruptSysCallMsg =
       
  1148         "Interrupted system call";
       
  1149 }