1071 lines · 42.4 KB · Java
RawDownload
/* * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package com.sun.jmx.snmp.agent; import java.util.Vector;import java.util.ArrayList;import java.util.Hashtable;import java.util.Enumeration;import java.util.Iterator;import java.util.List;import java.util.NoSuchElementException;import java.util.Arrays;import java.util.logging.Level; import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER;import com.sun.jmx.snmp.SnmpVarBind;import com.sun.jmx.snmp.SnmpStatusException;import com.sun.jmx.snmp.SnmpDefinitions;import com.sun.jmx.snmp.SnmpOid;import com.sun.jmx.snmp.SnmpPdu;import com.sun.jmx.snmp.SnmpEngine; //  XXX: things to do: use SnmpOid rather than `instance' for future//       evolutions.//  XXX: Maybe use hashlists rather than vectors for entries?//       => in that case, the key should be SnmpOid.toString()///** * This class is used to register varbinds from a SNMP varbind list with * the SnmpMibNode responsible for handling the requests concerning that * varbind. * This class holds a hashtable of Handler nodes, whith the involved * SnmpMibNode as a key. * When the involved SnmpMibNode is a group, the sublist of varbind is * directly stored in the Handler node. * When the involved SnmpMibNode is a table, the sublist is stored in a * sorted array indexed by the OID of the entry involved. */final class SnmpRequestTree {     // Constructor:    // @param  req The SnmpMibRequest that will be segmented in this    //         tree. It holds the original varbind vector passed    //         by the SnmpSubRequestHandler to this MIB. This    //         varbind vector is used to retrieve the "real"    //         position of a varbind in the vector. There is no other easy    //         way to do this - since as a result of the segmentation the    //         original positions will be lost.    // @param  creationflag indicates whether the operation involved    //         allows for entry creation (ie: it is a SET request).    // @param  pdutype indicates the type of the request PDU as defined    //         in SnmpDefinitions    //    SnmpRequestTree(SnmpMibRequest req, boolean creationflag, int pdutype) {        this.request = req;        this.version  = req.getVersion();        this.creationflag = creationflag;        this.hashtable = new Hashtable<Object, Handler>();        setPduType(pdutype);    }     public static int mapSetException(int errorStatus, int version)        throws SnmpStatusException {         final int errorCode = errorStatus;         if (version == SnmpDefinitions.snmpVersionOne)            return errorCode;         int mappedErrorCode = errorCode;         // Now take care of V2 errorCodes that can be stored        // in the varbind itself:        if (errorCode == SnmpStatusException.noSuchObject)            // noSuchObject => notWritable            mappedErrorCode = SnmpStatusException.snmpRspNotWritable;         else if (errorCode == SnmpStatusException.noSuchInstance)            // noSuchInstance => notWritable            mappedErrorCode = SnmpStatusException.snmpRspNotWritable;         return mappedErrorCode;    }     public static int mapGetException(int errorStatus, int version)        throws SnmpStatusException {         final int errorCode = errorStatus;        if (version == SnmpDefinitions.snmpVersionOne)            return errorCode;         int mappedErrorCode = errorCode;         // Now take care of V2 errorCodes that can be stored        // in the varbind itself:        if (errorCode ==            SnmpStatusException.noSuchObject)            // noSuchObject => noSuchObject            mappedErrorCode = errorCode;         else if (errorCode ==                 SnmpStatusException.noSuchInstance)            // noSuchInstance => noSuchInstance            mappedErrorCode = errorCode;         // Now we're going to try to transform every other        // global code in either noSuchInstance or noSuchObject,        // so that the get can return a partial result.        //        // Only noSuchInstance or noSuchObject can be stored        // in the varbind itself.        //         // According to RFC 1905: noAccess is emitted when the        // the access is denied because it is not in the MIB view...        //        else if (errorCode ==                 SnmpStatusException.noAccess)            // noAccess => noSuchInstance            mappedErrorCode = SnmpStatusException.noSuchInstance;         // According to RFC 1905: (my interpretation because it is not        // really clear) The specified variable name exists - but the        // variable does not exists and cannot be created under the        // present circumstances (probably because the request specifies        // another variable/value which is incompatible, or because the        // value of some other variable in the MIB prevents the creation)        //        // Note that this error should never be raised in a GET context        // but who knows?        //        else if (errorCode == SnmpStatusException.snmpRspInconsistentName)            // inconsistentName => noSuchInstance            mappedErrorCode = SnmpStatusException.noSuchInstance;         // All the errors comprised between snmpRspWrongType and        // snmpRspInconsistentValue concern values: so we're going        // to assume the OID was correct, and reply with noSuchInstance.        //        // Note that this error should never be raised in a GET context        // but who knows?        //        else if ((errorCode >= SnmpStatusException.snmpRspWrongType) &&                 (errorCode <= SnmpStatusException.snmpRspInconsistentValue))            mappedErrorCode = SnmpStatusException.noSuchInstance;         // We're going to assume the OID was correct, and reply        // with noSuchInstance.        //        else if (errorCode == SnmpStatusException.readOnly)            mappedErrorCode = SnmpStatusException.noSuchInstance;         // For all other errors but genErr, we're going to reply with        // noSuchObject        //        else if (errorCode != SnmpStatusException.snmpRspAuthorizationError &&                 errorCode != SnmpStatusException.snmpRspGenErr)            mappedErrorCode = SnmpStatusException.noSuchObject;         // Only genErr will abort the GET and be returned as global        // error.        //        return mappedErrorCode;     }     //-------------------------------------------------------------------    // This class is a package implementation of the enumeration of    // SnmSubRequest associated with an Handler node.    //-------------------------------------------------------------------     static final class Enum implements Enumeration {        Enum(SnmpRequestTree hlist,Handler h) {            handler = h;            this.hlist = hlist;            size = h.getSubReqCount();        }        private final Handler handler;        private final SnmpRequestTree hlist;        private int   entry = 0;        private int   iter  = 0;        private int   size  = 0;         public boolean hasMoreElements() {            return iter < size;        }         public Object nextElement() throws NoSuchElementException  {            if (iter == 0) {                if (handler.sublist != null) {                    iter++;                    return hlist.getSubRequest(handler);                }            }            iter ++;            if (iter > size) throw new NoSuchElementException();            Object result = hlist.getSubRequest(handler,entry);            entry++;            return result;        }    }     //-------------------------------------------------------------------    // This class is a package implementation of the SnmpMibSubRequest    // interface. It can only be instantiated by SnmpRequestTree.    //-------------------------------------------------------------------     static final class SnmpMibSubRequestImpl implements SnmpMibSubRequest {        SnmpMibSubRequestImpl(SnmpMibRequest global, Vector<SnmpVarBind> sublist,                           SnmpOid entryoid, boolean isnew,                           boolean getnextflag, SnmpVarBind rs) {            this.global = global;            varbinds           = sublist;            this.version       = global.getVersion();            this.entryoid      = entryoid;            this.isnew         = isnew;            this.getnextflag   = getnextflag;            this.statusvb      = rs;        }         final private Vector<SnmpVarBind> varbinds;        final private SnmpMibRequest global;        final private int            version;        final private boolean        isnew;        final private SnmpOid        entryoid;        final private boolean        getnextflag;        final private SnmpVarBind    statusvb;         // -------------------------------------------------------------        // Implements the method defined in SnmpMibRequest interface.        // See SnmpMibRequest for the java doc.        // -------------------------------------------------------------        public Enumeration getElements() {            return varbinds.elements();        }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibRequest interface.        // See SnmpMibRequest for the java doc.        // -------------------------------------------------------------        public Vector<SnmpVarBind> getSubList() {            return varbinds;        }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibRequest interface.        // See SnmpMibRequest for the java doc.        // -------------------------------------------------------------        public final int getSize()  {            if (varbinds == null) return 0;            return varbinds.size();        }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibRequest interface.        // See SnmpMibRequest for the java doc.        // -------------------------------------------------------------        public void addVarBind(SnmpVarBind varbind) {            // XXX not sure we must also add the varbind in the global            //     request? or whether we should raise an exception:            //     in principle, this method should not be called!            varbinds.addElement(varbind);            global.addVarBind(varbind);        }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibSubRequest interface.        // See SnmpMibSubRequest for the java doc.        // -------------------------------------------------------------        public boolean isNewEntry() {            return isnew;        }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibSubRequest interface.        // See SnmpMibSubRequest for the java doc.        // -------------------------------------------------------------        public SnmpOid getEntryOid() {            return entryoid;        }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibRequest interface.        // See SnmpMibRequest for the java doc.        // -------------------------------------------------------------        public int getVarIndex(SnmpVarBind varbind) {            if (varbind == null) return 0;            return global.getVarIndex(varbind);        }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibRequest interface.        // See SnmpMibRequest for the java doc.        // -------------------------------------------------------------        public Object getUserData() { return global.getUserData(); }          // -------------------------------------------------------------        // Implements the method defined in SnmpMibSubRequest interface.        // See SnmpMibSubRequest for the java doc.        // -------------------------------------------------------------         public void registerGetException(SnmpVarBind var,                                         SnmpStatusException exception)            throws SnmpStatusException {            // The index in the exception must correspond to            // the SNMP index ...            //            if (version == SnmpDefinitions.snmpVersionOne)                throw new SnmpStatusException(exception, getVarIndex(var)+1);             if (var == null)                throw exception;             // If we're doing a getnext ==> endOfMibView            if (getnextflag) {                var.value = SnmpVarBind.endOfMibView;                return;            }             final int errorCode = mapGetException(exception.getStatus(),                                                  version);             // Now take care of V2 errorCodes that can be stored            // in the varbind itself:            if (errorCode ==                SnmpStatusException.noSuchObject)                // noSuchObject => noSuchObject                var.value= SnmpVarBind.noSuchObject;             else if (errorCode ==                     SnmpStatusException.noSuchInstance)                // noSuchInstance => noSuchInstance                var.value= SnmpVarBind.noSuchInstance;             else                throw new SnmpStatusException(errorCode, getVarIndex(var)+1);         }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibSubRequest interface.        // See SnmpMibSubRequest for the java doc.        // -------------------------------------------------------------        public void registerSetException(SnmpVarBind var,                                         SnmpStatusException exception)            throws SnmpStatusException {            // The index in the exception must correspond to            // the SNMP index ...            //            if (version == SnmpDefinitions.snmpVersionOne)                throw new SnmpStatusException(exception, getVarIndex(var)+1);             // Although the first pass of check() did not fail,            // the set() phase could not be carried out correctly.            // Since we don't know how to make an "undo", and some            // assignation may already have been performed, we're going            // to throw an snmpRspUndoFailed.            //            throw new SnmpStatusException(SnmpDefinitions.snmpRspUndoFailed,                                          getVarIndex(var)+1);        }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibSubRequest interface.        // See SnmpMibSubRequest for the java doc.        // -------------------------------------------------------------        public void registerCheckException(SnmpVarBind var,                                           SnmpStatusException exception)            throws SnmpStatusException {            // The index in the exception must correspond to            // the SNMP index ...            //            // We throw the exception in order to abort the SET operation            // in an atomic way.            final int errorCode = exception.getStatus();            final int mappedErrorCode = mapSetException(errorCode,                                                        version);             if (errorCode != mappedErrorCode)                throw new                    SnmpStatusException(mappedErrorCode, getVarIndex(var)+1);            else                throw new SnmpStatusException(exception, getVarIndex(var)+1);        }         // -------------------------------------------------------------        // Implements the method defined in SnmpMibRequest interface.        // See SnmpMibRequest for the java doc.        // -------------------------------------------------------------        public int getVersion() {            return version;        }         public SnmpVarBind getRowStatusVarBind() {            return statusvb;        }         public SnmpPdu getPdu() {            return global.getPdu();        }         public int getRequestPduVersion() {            return global.getRequestPduVersion();        }         public SnmpEngine getEngine() {            return global.getEngine();        }         public String getPrincipal() {            return global.getPrincipal();        }         public int getSecurityLevel() {            return global.getSecurityLevel();        }         public int getSecurityModel() {            return global.getSecurityModel();        }         public byte[] getContextName() {            return global.getContextName();        }         public byte[] getAccessContextName() {            return global.getAccessContextName();        }    }     //-------------------------------------------------------------------    // This class implements a node in the SnmpRequestTree.    // It stores:    //    o The SnmpMibNode involved (key)    //    o The sublist of varbind directly handled by this node    //    o A vector of sublists concerning the entries (existing or not)    //      of the SnmpMIbNode (when it is a table).    //-------------------------------------------------------------------     static final class Handler {        SnmpMibNode meta;       // The meta  which handles the sublist.        int         depth;      // The depth of the meta node.        Vector<SnmpVarBind> sublist; // The sublist of varbinds to be handled.        // List        entryoids;  // Sorted array of entry oids        // List        entrylists; // Sorted array of entry lists        // List        isentrynew; // Sorted array of booleans        SnmpOid[]     entryoids  = null; // Sorted array of entry oids        Vector<SnmpVarBind>[] entrylists = null; // Sorted array of entry lists        boolean[]     isentrynew = null; // Sorted array of booleans        SnmpVarBind[] rowstatus  = null; // RowStatus varbind, if any        int entrycount = 0;        int entrysize  = 0;         final int type; // request PDU type as defined in SnmpDefinitions        final private static int Delta = 10;         public Handler(int pduType) {            this.type = pduType;        }         /**         * Adds a varbind in this node sublist.         */        public void addVarbind(SnmpVarBind varbind) {            if (sublist == null) sublist = new Vector<SnmpVarBind>();            sublist.addElement(varbind);        }         /**         * register an entry for the given oid at the given position with         * the given sublist.         */        @SuppressWarnings("unchecked")        // We need this because of new Vector[n] instead of        // new Vector<SnmpVarBind>[n], which is illegal.        void add(int pos,SnmpOid oid, Vector<SnmpVarBind> v, boolean isnew,                 SnmpVarBind statusvb) {

Lines 1–500 of 1071.