jdk/src/jdk.snmp/share/classes/com/sun/jmx/snmp/internal/SnmpEngineImpl.java
changeset 27188 a1aa62221649
parent 27187 020b64fc02df
child 27189 b90845965ee9
equal deleted inserted replaced
27187:020b64fc02df 27188:a1aa62221649
     1 /*
       
     2  * Copyright (c) 2001, 2006, 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 package com.sun.jmx.snmp.internal;
       
    26 
       
    27 import java.net.InetAddress;
       
    28 import java.net.UnknownHostException;
       
    29 import java.util.Hashtable;
       
    30 import java.util.logging.Level;
       
    31 import java.io.Serializable;
       
    32 
       
    33 import com.sun.jmx.snmp.SnmpDefinitions;
       
    34 import com.sun.jmx.snmp.SnmpEngineId;
       
    35 import com.sun.jmx.snmp.SnmpEngine;
       
    36 import com.sun.jmx.snmp.SnmpUsmKeyHandler;
       
    37 import com.sun.jmx.snmp.SnmpEngineFactory;
       
    38 import com.sun.jmx.snmp.SnmpUnknownModelException;
       
    39 
       
    40 import com.sun.jmx.snmp.internal.SnmpTools;
       
    41 import com.sun.jmx.snmp.SnmpBadSecurityLevelException;
       
    42 import static com.sun.jmx.defaults.JmxProperties.SNMP_LOGGER;
       
    43 
       
    44 /**
       
    45  * This engine is conformant with the RFC 2571. It is the main object within
       
    46  * an SNMP entity (agent, manager...).
       
    47  * To an engine is associated an {@link com.sun.jmx.snmp.SnmpEngineId}.
       
    48  * The way the engineId is retrieved is linked to the way the engine is
       
    49  * instantiated. See each <CODE>SnmpEngine</CODE> constructor for more details.
       
    50  * An engine is composed of a set of sub systems
       
    51  * {@link com.sun.jmx.snmp.internal.SnmpSubSystem}. An <CODE>SNMP</CODE>
       
    52  * engine can contain a:
       
    53  *<ul>
       
    54  *<li> Message Processing Sub System :
       
    55  * {@link com.sun.jmx.snmp.internal.SnmpMsgProcessingSubSystem}</li>
       
    56  *<li> Security Sub System :
       
    57  * {@link com.sun.jmx.snmp.internal.SnmpSecuritySubSystem} </li>
       
    58  *<li> Access Control Sub System :
       
    59  * {@link com.sun.jmx.snmp.internal.SnmpAccessControlSubSystem}</li>
       
    60  *</ul>
       
    61  *<P> Each sub system contains a set of models. A model is an implementation
       
    62  * of a particular treatement (eg: the User based Security Model defined in
       
    63  * RFC 2574 is a functional element dealing with authentication and privacy).
       
    64  *</P>
       
    65  * Engine instantiation is based on a factory. This factory, implementing
       
    66  * mandatorily {@link com.sun.jmx.snmp.SnmpEngineFactory  SnmpEngineFactory}
       
    67  * is set in the method <CODE>setFactory</CODE>.
       
    68  * <p><b>This API is a Sun Microsystems internal API  and is subject
       
    69  * to change without notice.</b></p>
       
    70  * @since 1.5
       
    71  */
       
    72 public class SnmpEngineImpl implements SnmpEngine, Serializable {
       
    73     private static final long serialVersionUID = -2564301391365614725L;
       
    74 
       
    75     /**
       
    76      * Security level. No authentication, no privacy. Value is 0,
       
    77      * as defined in RFC 2572
       
    78      */
       
    79     public static final int noAuthNoPriv = 0;
       
    80     /**
       
    81      * Security level. Authentication, no privacy. Value is 1, as
       
    82      * defined in RFC 2572
       
    83      */
       
    84     public static final int authNoPriv = 1;
       
    85     /**
       
    86      * Security level. Authentication, privacy. Value is 3,
       
    87      * as defined in RFC 2572
       
    88      */
       
    89     public static final int authPriv = 3;
       
    90     /**
       
    91      * Flag that indicates that a report is to be sent. Value is 4, as defined in RFC 2572
       
    92      */
       
    93     public static final int reportableFlag = 4;
       
    94 
       
    95     /**
       
    96      * Mask used to isolate authentication information within a message flag.
       
    97      */
       
    98     public static final int authMask = 1;
       
    99     /**
       
   100      * Mask used to isolate privacy information within a message flag.
       
   101      */
       
   102     public static final int privMask = 2;
       
   103     /**
       
   104      * Mask used to isolate authentication and privacy information within a message flag.
       
   105      */
       
   106     public static final int authPrivMask = 3;
       
   107 
       
   108     private SnmpEngineId engineid = null;
       
   109     private SnmpEngineFactory factory = null;
       
   110     private long startTime = 0;
       
   111 
       
   112     private int boot = 0;
       
   113     private boolean checkOid = false;
       
   114 
       
   115     transient private SnmpUsmKeyHandler usmKeyHandler = null;
       
   116     transient private SnmpLcd lcd = null;
       
   117 
       
   118     transient private SnmpSecuritySubSystem securitySub = null;
       
   119 
       
   120     transient private SnmpMsgProcessingSubSystem messageSub = null;
       
   121 
       
   122     transient private SnmpAccessControlSubSystem accessSub = null;
       
   123 
       
   124     /**
       
   125      * Gets the engine time in seconds. This is the time from the last reboot.
       
   126      * @return The time from the last reboot.
       
   127      */
       
   128     public synchronized int getEngineTime() {
       
   129         //We do the counter wrap in a lazt way. Each time Engine is asked for his time it checks. So if nobody use the Engine, the time can wrap and wrap again without incrementing nb boot. We can imagine that it is irrelevant due to the amount of time needed to wrap.
       
   130         long delta = (System.currentTimeMillis() / 1000) - startTime;
       
   131         if(delta >  0x7FFFFFFF) {
       
   132             //67 years of running. That is a great thing!
       
   133             //Reinitialize startTime.
       
   134             startTime = System.currentTimeMillis() / 1000;
       
   135 
       
   136             //Can't do anything with this counter.
       
   137             if(boot != 0x7FFFFFFF)
       
   138                 boot += 1;
       
   139             //Store for future use.
       
   140             storeNBBoots(boot);
       
   141         }
       
   142 
       
   143         return (int) ((System.currentTimeMillis() / 1000) - startTime);
       
   144     }
       
   145 
       
   146     /**
       
   147      * Gets the engine Id. This is unique for each engine.
       
   148      * @return The engine Id object.
       
   149      */
       
   150     public SnmpEngineId getEngineId() {
       
   151         return engineid;
       
   152     }
       
   153 
       
   154     /**
       
   155      * Gets the Usm key handler.
       
   156      * @return The key handler.
       
   157      */
       
   158     public SnmpUsmKeyHandler getUsmKeyHandler() {
       
   159         return usmKeyHandler;
       
   160     }
       
   161 
       
   162     /**
       
   163      * Gets the engine Lcd.
       
   164      * @return The engine Lcd.
       
   165      */
       
   166     public SnmpLcd getLcd() {
       
   167         return lcd;
       
   168     }
       
   169     /**
       
   170      * Gets the engine boot number. This is the number of time this engine has rebooted. Each time an <CODE>SnmpEngine</CODE> is instantiated, it will read this value in its Lcd, and store back the value incremented by one.
       
   171      * @return The engine's number of reboot.
       
   172      */
       
   173     public int getEngineBoots() {
       
   174         return boot;
       
   175     }
       
   176 
       
   177      /**
       
   178      * Constructor. A Local Configuration Datastore is passed to the engine. It will be used to store and retrieve data (engine Id, engine boots).
       
   179      * <P> WARNING : The SnmpEngineId is computed as follow:
       
   180      * <ul>
       
   181      * <li> If an lcd file is provided containing the property "localEngineID", this property value is used.</li>.
       
   182      * <li> If not, if the passed engineID is not null, this engine ID is used.</li>
       
   183      * <li> If not, a time based engineID is computed.</li>
       
   184      * </ul>
       
   185      * This constructor should be called by an <CODE>SnmpEngineFactory</CODE>. Don't call it directly.
       
   186      * @param fact The factory used to instantiate this engine.
       
   187      * @param lcd The local configuration datastore.
       
   188      * @param engineid The engine ID to use. If null is provided, an SnmpEngineId is computed using the current time.
       
   189      * @throws UnknownHostException Exception thrown, if the host name located in the property "localEngineID" is invalid.
       
   190      */
       
   191     public SnmpEngineImpl(SnmpEngineFactory fact,
       
   192                           SnmpLcd lcd,
       
   193                           SnmpEngineId engineid) throws UnknownHostException {
       
   194 
       
   195         init(lcd, fact);
       
   196         initEngineID();
       
   197         if(this.engineid == null) {
       
   198             if(engineid != null)
       
   199                 this.engineid = engineid;
       
   200             else
       
   201                 this.engineid = SnmpEngineId.createEngineId();
       
   202         }
       
   203         lcd.storeEngineId(this.engineid);
       
   204         if (SNMP_LOGGER.isLoggable(Level.FINER)) {
       
   205             SNMP_LOGGER.logp(Level.FINER, SnmpEngineImpl.class.getName(),
       
   206                     "SnmpEngineImpl(SnmpEngineFactory,SnmpLcd,SnmpEngineId)",
       
   207                     "LOCAL ENGINE ID: " + this.engineid);
       
   208         }
       
   209     }
       
   210     /**
       
   211      * Constructor. A Local Configuration Datastore is passed to the engine. It will be used to store and retrieve data (engine ID, engine boots).
       
   212      * <P> WARNING : The SnmpEngineId is computed as follow:
       
   213      * <ul>
       
   214      * <li> If an lcd file is provided containing the property "localEngineID", this property value is used.</li>.
       
   215      * <li> If not, the passed address and port are used to compute one.</li>
       
   216      * </ul>
       
   217      * This constructor should be called by an <CODE>SnmpEngineFactory</CODE>. Don't call it directly.
       
   218      * @param fact The factory used to instantiate this engine.
       
   219      * @param lcd The local configuration datastore.
       
   220      * @param port UDP port to use in order to calculate the engine ID.
       
   221      * @param address An IP address used to calculate the engine ID.
       
   222      * @throws UnknownHostException Exception thrown, if the host name located in the property "localEngineID" is invalid.
       
   223      */
       
   224     public SnmpEngineImpl(SnmpEngineFactory fact,
       
   225                           SnmpLcd lcd,
       
   226                           InetAddress address,
       
   227                           int port) throws UnknownHostException {
       
   228         init(lcd, fact);
       
   229         initEngineID();
       
   230         if(engineid == null)
       
   231             engineid = SnmpEngineId.createEngineId(address, port);
       
   232 
       
   233         lcd.storeEngineId(engineid);
       
   234 
       
   235         if (SNMP_LOGGER.isLoggable(Level.FINER)) {
       
   236             SNMP_LOGGER.logp(Level.FINER, SnmpEngineImpl.class.getName(),
       
   237                     "SnmpEngineImpl(SnmpEngineFactory,SnmpLcd,InetAddress,int)",
       
   238                     "LOCAL ENGINE ID: " + engineid + " / " +
       
   239                     "LOCAL ENGINE NB BOOTS: " + boot + " / " +
       
   240                     "LOCAL ENGINE START TIME: " + getEngineTime());
       
   241         }
       
   242     }
       
   243 
       
   244     /**
       
   245      * Constructor. A Local Configuration Datastore is passed to the engine. It will be used to store and retrieve data (engine ID, engine boots).
       
   246      * <P> WARNING : The SnmpEngineId is computed as follow:
       
   247      * <ul>
       
   248      * <li> If an lcd file is provided containing the property "localEngineID", this property value is used.</li>.
       
   249      * <li> If not, The passed port is used to compute one.</li>
       
   250      * </ul>
       
   251      * This constructor should be called by an <CODE>SnmpEngineFactory</CODE>. Don't call it directly.
       
   252      * @param fact The factory used to instantiate this engine.
       
   253      * @param lcd The local configuration datastore
       
   254      * @param port UDP port to use in order to calculate the engine ID.
       
   255      * @throws UnknownHostException Exception thrown, if the host name located in the property "localEngineID" is invalid.
       
   256      */
       
   257     public SnmpEngineImpl(SnmpEngineFactory fact,
       
   258                           SnmpLcd lcd,
       
   259                           int port) throws UnknownHostException {
       
   260         init(lcd, fact);
       
   261         initEngineID();
       
   262         if(engineid == null)
       
   263            engineid = SnmpEngineId.createEngineId(port);
       
   264 
       
   265         lcd.storeEngineId(engineid);
       
   266 
       
   267         if (SNMP_LOGGER.isLoggable(Level.FINER)) {
       
   268             SNMP_LOGGER.logp(Level.FINER, SnmpEngineImpl.class.getName(),
       
   269                     "SnmpEngineImpl(SnmpEngineFactory,SnmpLcd,int)",
       
   270                     "LOCAL ENGINE ID: " + engineid + " / " +
       
   271                     "LOCAL ENGINE NB BOOTS: " + boot + " / " +
       
   272                     "LOCAL ENGINE START TIME: " + getEngineTime());
       
   273         }
       
   274     }
       
   275 
       
   276     /**
       
   277      * Constructor. A Local Configuration Datastore is passed to the engine. It will be used to store and retrieve data (engine ID, engine boots).
       
   278      * <P> WARNING : The SnmpEngineId is computed as follow:
       
   279      * <ul>
       
   280      * <li> If an lcd file is provided containing the property "localEngineID", this property value is used.</li>.
       
   281      * <li> If not, a time based engineID is computed.</li>
       
   282      * </ul>
       
   283      * When no configuration nor java property is set for the engine ID value, a unique time based engine ID will be generated.
       
   284      * This constructor should be called by an <CODE>SnmpEngineFactory</CODE>. Don't call it directly.
       
   285      * @param fact The factory used to instantiate this engine.
       
   286      * @param lcd The local configuration datastore.
       
   287      */
       
   288     public SnmpEngineImpl(SnmpEngineFactory fact,
       
   289                           SnmpLcd lcd) throws UnknownHostException {
       
   290         init(lcd, fact);
       
   291         initEngineID();
       
   292         if(engineid == null)
       
   293             engineid = SnmpEngineId.createEngineId();
       
   294 
       
   295         lcd.storeEngineId(engineid);
       
   296 
       
   297         if (SNMP_LOGGER.isLoggable(Level.FINER)) {
       
   298             SNMP_LOGGER.logp(Level.FINER, SnmpEngineImpl.class.getName(),
       
   299                     "SnmpEngineImpl(SnmpEngineFactory,SnmpLcd)",
       
   300                     "LOCAL ENGINE ID: " + engineid + " / " +
       
   301                     "LOCAL ENGINE NB BOOTS: " + boot + " / " +
       
   302                     "LOCAL ENGINE START TIME: " + getEngineTime());
       
   303         }
       
   304     }
       
   305 
       
   306     /**
       
   307      * Access Control will check the oids. By default is false.
       
   308      */
       
   309     public synchronized void activateCheckOid() {
       
   310         checkOid = true;
       
   311     }
       
   312 
       
   313     /**
       
   314      * Access Control will not check the oids. By default is false.
       
   315      */
       
   316     public synchronized void deactivateCheckOid() {
       
   317         checkOid = false;
       
   318     }
       
   319 
       
   320     /**
       
   321      * Access Control check or not the oids. By default is false.
       
   322      */
       
   323     public synchronized boolean isCheckOidActivated() {
       
   324         return checkOid;
       
   325     }
       
   326 
       
   327     //Do some check and store the nb boots value.
       
   328     private void storeNBBoots(int boot) {
       
   329         if(boot < 0 || boot == 0x7FFFFFFF) {
       
   330             boot = 0x7FFFFFFF;
       
   331             lcd.storeEngineBoots(boot);
       
   332         }
       
   333         else
       
   334             lcd.storeEngineBoots(boot + 1);
       
   335     }
       
   336 
       
   337     // Initialize internal status.
       
   338     private void init(SnmpLcd lcd, SnmpEngineFactory fact) {
       
   339         this.factory = fact;
       
   340         this.lcd = lcd;
       
   341         boot = lcd.getEngineBoots();
       
   342 
       
   343         if(boot == -1 || boot == 0)
       
   344             boot = 1;
       
   345 
       
   346         storeNBBoots(boot);
       
   347 
       
   348         startTime = System.currentTimeMillis() / 1000;
       
   349 
       
   350     }
       
   351 
       
   352     void setUsmKeyHandler(SnmpUsmKeyHandler usmKeyHandler) {
       
   353         this.usmKeyHandler = usmKeyHandler;
       
   354     }
       
   355 
       
   356     //Initialize the engineID.
       
   357     private void initEngineID() throws UnknownHostException {
       
   358         String id = lcd.getEngineId();
       
   359         if(id != null) {
       
   360             engineid = SnmpEngineId.createEngineId(id);
       
   361         }
       
   362     }
       
   363 
       
   364 
       
   365     /**
       
   366      * Returns the Message Processing Sub System.
       
   367      * @return The Message Processing Sub System.
       
   368      */
       
   369     public SnmpMsgProcessingSubSystem getMsgProcessingSubSystem() {
       
   370         return messageSub;
       
   371     }
       
   372 
       
   373     /**
       
   374      * Sets the Message Processing Sub System.
       
   375      * @param sys The Message Processing Sub System.
       
   376      */
       
   377     public void setMsgProcessingSubSystem(SnmpMsgProcessingSubSystem sys) {
       
   378         messageSub = sys;
       
   379     }
       
   380 
       
   381      /**
       
   382      * Returns the Security Sub System.
       
   383      * @return The Security Sub System.
       
   384      */
       
   385     public SnmpSecuritySubSystem getSecuritySubSystem() {
       
   386         return securitySub;
       
   387     }
       
   388     /**
       
   389      * Sets the Security Sub System.
       
   390      * @param sys The Security Sub System.
       
   391      */
       
   392     public void setSecuritySubSystem(SnmpSecuritySubSystem sys) {
       
   393         securitySub = sys;
       
   394     }
       
   395      /**
       
   396      * Sets the Access Control Sub System.
       
   397      * @param sys The Access Control Sub System.
       
   398      */
       
   399     public void setAccessControlSubSystem(SnmpAccessControlSubSystem sys) {
       
   400         accessSub = sys;
       
   401     }
       
   402 
       
   403     /**
       
   404      * Returns the Access Control Sub System.
       
   405      * @return The Access Control Sub System.
       
   406      */
       
   407     public SnmpAccessControlSubSystem getAccessControlSubSystem() {
       
   408         return accessSub;
       
   409     }
       
   410     /**
       
   411      * Checks the passed msg flags according to the rules specified in RFC 2572.
       
   412      * @param msgFlags The msg flags.
       
   413      */
       
   414     public static void checkSecurityLevel(byte msgFlags)
       
   415         throws SnmpBadSecurityLevelException {
       
   416         int secLevel = msgFlags & SnmpDefinitions.authPriv;
       
   417         if((secLevel & SnmpDefinitions.privMask) != 0)
       
   418             if((secLevel & SnmpDefinitions.authMask) == 0) {
       
   419                 throw new SnmpBadSecurityLevelException("Security level:"+
       
   420                                                         " noAuthPriv!!!");
       
   421             }
       
   422     }
       
   423 
       
   424 }