| /* |
| * Copyright (c) 1997, 2012, 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.daemon; |
| |
| |
| // java imports |
| // |
| import java.util.Vector; |
| import java.util.Enumeration; |
| import java.util.logging.Level; |
| import java.net.DatagramSocket; |
| import java.net.DatagramPacket; |
| import java.net.InetAddress; |
| import java.net.SocketException; |
| import java.net.UnknownHostException; |
| import java.io.ObjectInputStream; |
| import java.io.IOException; |
| import java.io.InterruptedIOException; |
| |
| |
| // jmx imports |
| // |
| import javax.management.MBeanServer; |
| import javax.management.MBeanRegistration; |
| import javax.management.ObjectName; |
| import static com.sun.jmx.defaults.JmxProperties.SNMP_ADAPTOR_LOGGER; |
| import com.sun.jmx.snmp.SnmpIpAddress; |
| import com.sun.jmx.snmp.SnmpMessage; |
| import com.sun.jmx.snmp.SnmpOid; |
| import com.sun.jmx.snmp.SnmpPduFactory; |
| import com.sun.jmx.snmp.SnmpPduPacket; |
| import com.sun.jmx.snmp.SnmpPduRequest; |
| import com.sun.jmx.snmp.SnmpPduTrap; |
| import com.sun.jmx.snmp.SnmpTimeticks; |
| import com.sun.jmx.snmp.SnmpVarBind; |
| import com.sun.jmx.snmp.SnmpVarBindList; |
| import com.sun.jmx.snmp.SnmpDefinitions; |
| import com.sun.jmx.snmp.SnmpStatusException; |
| import com.sun.jmx.snmp.SnmpTooBigException; |
| import com.sun.jmx.snmp.InetAddressAcl; |
| import com.sun.jmx.snmp.SnmpPeer; |
| import com.sun.jmx.snmp.SnmpParameters; |
| // SNMP Runtime imports |
| // |
| import com.sun.jmx.snmp.SnmpPduFactoryBER; |
| import com.sun.jmx.snmp.agent.SnmpMibAgent; |
| import com.sun.jmx.snmp.agent.SnmpMibHandler; |
| import com.sun.jmx.snmp.agent.SnmpUserDataFactory; |
| import com.sun.jmx.snmp.agent.SnmpErrorHandlerAgent; |
| |
| import com.sun.jmx.snmp.IPAcl.SnmpAcl; |
| |
| import com.sun.jmx.snmp.tasks.ThreadService; |
| |
| /** |
| * Implements an adaptor on top of the SNMP protocol. |
| * <P> |
| * When this SNMP protocol adaptor is started it creates a datagram socket |
| * and is able to receive requests and send traps or inform requests. |
| * When it is stopped, the socket is closed and neither requests |
| * and nor traps/inform request are processed. |
| * <P> |
| * The default port number of the socket is 161. This default value can be |
| * changed by specifying a port number: |
| * <UL> |
| * <LI>in the object constructor</LI> |
| * <LI>using the {@link com.sun.jmx.snmp.daemon.CommunicatorServer#setPort |
| * setPort} method before starting the adaptor</LI> |
| * </UL> |
| * The default object name is defined by {@link |
| * com.sun.jmx.snmp.ServiceName#DOMAIN com.sun.jmx.snmp.ServiceName.DOMAIN} |
| * and {@link com.sun.jmx.snmp.ServiceName#SNMP_ADAPTOR_SERVER |
| * com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_SERVER}. |
| * <P> |
| * The SNMP protocol adaptor supports versions 1 and 2 of the SNMP protocol |
| * in a stateless way: when it receives a v1 request, it replies with a v1 |
| * response, when it receives a v2 request it replies with a v2 response. |
| * <BR>The method {@link #snmpV1Trap snmpV1Trap} sends traps using SNMP v1 |
| * format. |
| * The method {@link #snmpV2Trap snmpV2Trap} sends traps using SNMP v2 format. |
| * The method {@link #snmpInformRequest snmpInformRequest} sends inform |
| * requests using SNMP v2 format. |
| * <P> |
| * To receive data packets, the SNMP protocol adaptor uses a buffer |
| * which size can be configured using the property <CODE>bufferSize</CODE> |
| * (default value is 1024). |
| * Packets which do not fit into the buffer are rejected. |
| * Increasing <CODE>bufferSize</CODE> allows the exchange of bigger packets. |
| * However, the underlying networking system may impose a limit on the size |
| * of UDP packets. |
| * Packets which size exceed this limit will be rejected, no matter what |
| * the value of <CODE>bufferSize</CODE> actually is. |
| * <P> |
| * An SNMP protocol adaptor may serve several managers concurrently. The |
| * number of concurrent managers can be limited using the property |
| * <CODE>maxActiveClientCount</CODE>. |
| * <p> |
| * The SNMP protocol adaptor specifies a default value (10) for the |
| * <CODE>maxActiveClientCount</CODE> property. When the adaptor is stopped, |
| * the active requests are interrupted and an error result is sent to |
| * the managers. |
| * <p><b>This API is a Sun Microsystems internal API and is subject |
| * to change without notice.</b></p> |
| */ |
| |
| public class SnmpAdaptorServer extends CommunicatorServer |
| implements SnmpAdaptorServerMBean, MBeanRegistration, SnmpDefinitions, |
| SnmpMibHandler { |
| |
| // PRIVATE VARIABLES |
| //------------------ |
| |
| /** |
| * Port number for sending SNMP traps. |
| * <BR>The default value is 162. |
| */ |
| private int trapPort = 162; |
| |
| /** |
| * Port number for sending SNMP inform requests. |
| * <BR>The default value is 162. |
| */ |
| private int informPort = 162; |
| |
| /** |
| * The <CODE>InetAddress</CODE> used when creating the datagram socket. |
| * <BR>It is specified when creating the SNMP protocol adaptor. |
| * If not specified, the local host machine is used. |
| */ |
| InetAddress address = null; |
| |
| /** |
| * The IP address based ACL used by this SNMP protocol adaptor. |
| */ |
| private InetAddressAcl ipacl = null; |
| |
| /** |
| * The factory object. |
| */ |
| private SnmpPduFactory pduFactory = null; |
| |
| /** |
| * The user-data factory object. |
| */ |
| private SnmpUserDataFactory userDataFactory = null; |
| |
| /** |
| * Indicates if the SNMP protocol adaptor sends a response in case |
| * of authentication failure |
| */ |
| private boolean authRespEnabled = true; |
| |
| /** |
| * Indicates if authentication traps are enabled. |
| */ |
| private boolean authTrapEnabled = true; |
| |
| /** |
| * The enterprise OID. |
| * <BR>The default value is "1.3.6.1.4.1.42". |
| */ |
| private SnmpOid enterpriseOid = new SnmpOid("1.3.6.1.4.1.42"); |
| |
| /** |
| * The buffer size of the SNMP protocol adaptor. |
| * This buffer size is used for both incoming request and outgoing |
| * inform requests. |
| * <BR>The default value is 1024. |
| */ |
| int bufferSize = 1024; |
| |
| private transient long startUpTime = 0; |
| private transient DatagramSocket socket = null; |
| transient DatagramSocket trapSocket = null; |
| private transient SnmpSession informSession = null; |
| private transient DatagramPacket packet = null; |
| transient Vector<SnmpMibAgent> mibs = new Vector<>(); |
| private transient SnmpMibTree root; |
| |
| /** |
| * Whether ACL must be used. |
| */ |
| private transient boolean useAcl = true; |
| |
| |
| // SENDING SNMP INFORMS STUFF |
| //--------------------------- |
| |
| /** |
| * Number of times to try an inform request before giving up. |
| * The default number is 3. |
| */ |
| private int maxTries = 3 ; |
| |
| /** |
| * The amount of time to wait for an inform response from the manager. |
| * The default amount of time is 3000 millisec. |
| */ |
| private int timeout = 3 * 1000 ; |
| |
| // VARIABLES REQUIRED FOR IMPLEMENTING SNMP GROUP (MIBII) |
| //------------------------------------------------------- |
| |
| /** |
| * The <CODE>snmpOutTraps</CODE> value defined in MIB-II. |
| */ |
| int snmpOutTraps=0; |
| |
| /** |
| * The <CODE>snmpOutGetResponses</CODE> value defined in MIB-II. |
| */ |
| private int snmpOutGetResponses=0; |
| |
| /** |
| * The <CODE>snmpOutGenErrs</CODE> value defined in MIB-II. |
| */ |
| private int snmpOutGenErrs=0; |
| |
| /** |
| * The <CODE>snmpOutBadValues</CODE> value defined in MIB-II. |
| */ |
| private int snmpOutBadValues=0; |
| |
| /** |
| * The <CODE>snmpOutNoSuchNames</CODE> value defined in MIB-II. |
| */ |
| private int snmpOutNoSuchNames=0; |
| |
| /** |
| * The <CODE>snmpOutTooBigs</CODE> value defined in MIB-II. |
| */ |
| private int snmpOutTooBigs=0; |
| |
| /** |
| * The <CODE>snmpOutPkts</CODE> value defined in MIB-II. |
| */ |
| int snmpOutPkts=0; |
| |
| /** |
| * The <CODE>snmpInASNParseErrs</CODE> value defined in MIB-II. |
| */ |
| private int snmpInASNParseErrs=0; |
| |
| /** |
| * The <CODE>snmpInBadCommunityUses</CODE> value defined in MIB-II. |
| */ |
| private int snmpInBadCommunityUses=0; |
| |
| /** |
| * The <CODE>snmpInBadCommunityNames</CODE> value defined in MIB-II. |
| */ |
| private int snmpInBadCommunityNames=0; |
| |
| /** |
| * The <CODE>snmpInBadVersions</CODE> value defined in MIB-II. |
| */ |
| private int snmpInBadVersions=0; |
| |
| /** |
| * The <CODE>snmpInGetRequests</CODE> value defined in MIB-II. |
| */ |
| private int snmpInGetRequests=0; |
| |
| /** |
| * The <CODE>snmpInGetNexts</CODE> value defined in MIB-II. |
| */ |
| private int snmpInGetNexts=0; |
| |
| /** |
| * The <CODE>snmpInSetRequests</CODE> value defined in MIB-II. |
| */ |
| private int snmpInSetRequests=0; |
| |
| /** |
| * The <CODE>snmpInPkts</CODE> value defined in MIB-II. |
| */ |
| private int snmpInPkts=0; |
| |
| /** |
| * The <CODE>snmpInTotalReqVars</CODE> value defined in MIB-II. |
| */ |
| private int snmpInTotalReqVars=0; |
| |
| /** |
| * The <CODE>snmpInTotalSetVars</CODE> value defined in MIB-II. |
| */ |
| private int snmpInTotalSetVars=0; |
| |
| /** |
| * The <CODE>snmpInTotalSetVars</CODE> value defined in rfc 1907 MIB-II. |
| */ |
| private int snmpSilentDrops=0; |
| |
| private static final String InterruptSysCallMsg = |
| "Interrupted system call"; |
| static final SnmpOid sysUpTimeOid = new SnmpOid("1.3.6.1.2.1.1.3.0") ; |
| static final SnmpOid snmpTrapOidOid = new SnmpOid("1.3.6.1.6.3.1.1.4.1.0"); |
| |
| private ThreadService threadService; |
| |
| private static int threadNumber = 6; |
| |
| static { |
| String s = System.getProperty("com.sun.jmx.snmp.threadnumber"); |
| |
| if (s != null) { |
| try { |
| threadNumber = Integer.parseInt(System.getProperty(s)); |
| } catch (Exception e) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, |
| SnmpAdaptorServer.class.getName(), |
| "<static init>", |
| "Got wrong value for com.sun.jmx.snmp.threadnumber: " + |
| s + ". Use the default value: " + threadNumber); |
| } |
| } |
| } |
| |
| // PUBLIC CONSTRUCTORS |
| //-------------------- |
| |
| /** |
| * Initializes this SNMP protocol adaptor using the default port (161). |
| * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default |
| * implementation of the <CODE>InetAddressAcl</CODE> interface. |
| */ |
| public SnmpAdaptorServer() { |
| this(true, null, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT, |
| null) ; |
| } |
| |
| /** |
| * Initializes this SNMP protocol adaptor using the specified port. |
| * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default |
| * implementation of the <CODE>InetAddressAcl</CODE> interface. |
| * |
| * @param port The port number for sending SNMP responses. |
| */ |
| public SnmpAdaptorServer(int port) { |
| this(true, null, port, null) ; |
| } |
| |
| /** |
| * Initializes this SNMP protocol adaptor using the default port (161) |
| * and the specified IP address based ACL implementation. |
| * |
| * @param acl The <CODE>InetAddressAcl</CODE> implementation. |
| * <code>null</code> means no ACL - everybody is authorized. |
| * |
| * @since 1.5 |
| */ |
| public SnmpAdaptorServer(InetAddressAcl acl) { |
| this(false, acl, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT, |
| null) ; |
| } |
| |
| /** |
| * Initializes this SNMP protocol adaptor using the default port (161) |
| * and the |
| * specified <CODE>InetAddress</CODE>. |
| * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default |
| * implementation of the <CODE>InetAddressAcl</CODE> interface. |
| * |
| * @param addr The IP address to bind. |
| */ |
| public SnmpAdaptorServer(InetAddress addr) { |
| this(true, null, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT, |
| addr) ; |
| } |
| |
| /** |
| * Initializes this SNMP protocol adaptor using the specified port and the |
| * specified IP address based ACL implementation. |
| * |
| * @param acl The <CODE>InetAddressAcl</CODE> implementation. |
| * <code>null</code> means no ACL - everybody is authorized. |
| * @param port The port number for sending SNMP responses. |
| * |
| * @since 1.5 |
| */ |
| public SnmpAdaptorServer(InetAddressAcl acl, int port) { |
| this(false, acl, port, null) ; |
| } |
| |
| /** |
| * Initializes this SNMP protocol adaptor using the specified port and the |
| * specified <CODE>InetAddress</CODE>. |
| * Use the {@link com.sun.jmx.snmp.IPAcl.SnmpAcl} default |
| * implementation of the <CODE>InetAddressAcl</CODE> interface. |
| * |
| * @param port The port number for sending SNMP responses. |
| * @param addr The IP address to bind. |
| */ |
| public SnmpAdaptorServer(int port, InetAddress addr) { |
| this(true, null, port, addr) ; |
| } |
| |
| /** |
| * Initializes this SNMP protocol adaptor using the specified IP |
| * address based ACL implementation and the specified |
| * <CODE>InetAddress</CODE>. |
| * |
| * @param acl The <CODE>InetAddressAcl</CODE> implementation. |
| * @param addr The IP address to bind. |
| * |
| * @since 1.5 |
| */ |
| public SnmpAdaptorServer(InetAddressAcl acl, InetAddress addr) { |
| this(false, acl, com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_PORT, |
| addr) ; |
| } |
| |
| /** |
| * Initializes this SNMP protocol adaptor using the specified port, the |
| * specified address based ACL implementation and the specified |
| * <CODE>InetAddress</CODE>. |
| * |
| * @param acl The <CODE>InetAddressAcl</CODE> implementation. |
| * @param port The port number for sending SNMP responses. |
| * @param addr The IP address to bind. |
| * |
| * @since 1.5 |
| */ |
| public SnmpAdaptorServer(InetAddressAcl acl, int port, InetAddress addr) { |
| this(false, acl, port, addr); |
| } |
| |
| /** |
| * Initializes this SNMP protocol adaptor using the specified port and the |
| * specified <CODE>InetAddress</CODE>. |
| * This constructor allows to initialize an SNMP adaptor without using |
| * the ACL mechanism (by setting the <CODE>useAcl</CODE> parameter to |
| * false). |
| * <br>This constructor must be used in particular with a platform that |
| * does not support the <CODE>java.security.acl</CODE> package like pJava. |
| * |
| * @param useAcl Specifies if this new SNMP adaptor uses the ACL mechanism. |
| * If the specified parameter is set to <CODE>true</CODE>, this |
| * constructor is equivalent to |
| * <CODE>SnmpAdaptorServer((int)port,(InetAddress)addr)</CODE>. |
| * @param port The port number for sending SNMP responses. |
| * @param addr The IP address to bind. |
| */ |
| public SnmpAdaptorServer(boolean useAcl, int port, InetAddress addr) { |
| this(useAcl,null,port,addr); |
| } |
| |
| // If forceAcl is `true' and InetAddressAcl is null, then a default |
| // SnmpAcl object is created. |
| // |
| private SnmpAdaptorServer(boolean forceAcl, InetAddressAcl acl, |
| int port, InetAddress addr) { |
| super(CommunicatorServer.SNMP_TYPE) ; |
| |
| |
| // Initialize the ACL implementation. |
| // |
| if (acl == null && forceAcl) { |
| try { |
| acl = new SnmpAcl("SNMP protocol adaptor IP ACL"); |
| } catch (UnknownHostException e) { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "constructor", "UnknowHostException when creating ACL",e); |
| } |
| } |
| } else { |
| this.useAcl = (acl!=null) || forceAcl; |
| } |
| |
| init(acl, port, addr) ; |
| } |
| |
| // GETTERS AND SETTERS |
| //-------------------- |
| |
| /** |
| * Gets the number of managers that have been processed by this |
| * SNMP protocol adaptor since its creation. |
| * |
| * @return The number of managers handled by this SNMP protocol adaptor |
| * since its creation. This counter is not reset by the <CODE>stop</CODE> |
| * method. |
| */ |
| @Override |
| public int getServedClientCount() { |
| return super.getServedClientCount(); |
| } |
| |
| /** |
| * Gets the number of managers currently being processed by this |
| * SNMP protocol adaptor. |
| * |
| * @return The number of managers currently being processed by this |
| * SNMP protocol adaptor. |
| */ |
| @Override |
| public int getActiveClientCount() { |
| return super.getActiveClientCount(); |
| } |
| |
| /** |
| * Gets the maximum number of managers that this SNMP protocol adaptor can |
| * process concurrently. |
| * |
| * @return The maximum number of managers that this SNMP protocol adaptor |
| * can process concurrently. |
| */ |
| @Override |
| public int getMaxActiveClientCount() { |
| return super.getMaxActiveClientCount(); |
| } |
| |
| /** |
| * Sets the maximum number of managers this SNMP protocol adaptor can |
| * process concurrently. |
| * |
| * @param c The number of managers. |
| * |
| * @exception java.lang.IllegalStateException This method has been invoked |
| * while the communicator was <CODE>ONLINE</CODE> or <CODE>STARTING</CODE>. |
| */ |
| @Override |
| public void setMaxActiveClientCount(int c) |
| throws java.lang.IllegalStateException { |
| super.setMaxActiveClientCount(c); |
| } |
| |
| /** |
| * Returns the Ip address based ACL used by this SNMP protocol adaptor. |
| * @return The <CODE>InetAddressAcl</CODE> implementation. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public InetAddressAcl getInetAddressAcl() { |
| return ipacl; |
| } |
| |
| /** |
| * Returns the port used by this SNMP protocol adaptor for sending traps. |
| * By default, port 162 is used. |
| * |
| * @return The port number for sending SNMP traps. |
| */ |
| @Override |
| public Integer getTrapPort() { |
| return new Integer(trapPort) ; |
| } |
| |
| /** |
| * Sets the port used by this SNMP protocol adaptor for sending traps. |
| * |
| * @param port The port number for sending SNMP traps. |
| */ |
| @Override |
| public void setTrapPort(Integer port) { |
| setTrapPort(port.intValue()); |
| } |
| |
| /** |
| * Sets the port used by this SNMP protocol adaptor for sending traps. |
| * |
| * @param port The port number for sending SNMP traps. |
| */ |
| public void setTrapPort(int port) { |
| int val= port ; |
| if (val < 0) throw new |
| IllegalArgumentException("Trap port cannot be a negative value"); |
| trapPort= val ; |
| } |
| |
| /** |
| * Returns the port used by this SNMP protocol adaptor for sending |
| * inform requests. By default, port 162 is used. |
| * |
| * @return The port number for sending SNMP inform requests. |
| */ |
| @Override |
| public int getInformPort() { |
| return informPort; |
| } |
| |
| /** |
| * Sets the port used by this SNMP protocol adaptor for sending |
| * inform requests. |
| * |
| * @param port The port number for sending SNMP inform requests. |
| */ |
| @Override |
| public void setInformPort(int port) { |
| if (port < 0) |
| throw new IllegalArgumentException("Inform request port "+ |
| "cannot be a negative value"); |
| informPort= port ; |
| } |
| |
| /** |
| * Returns the protocol of this SNMP protocol adaptor. |
| * |
| * @return The string "snmp". |
| */ |
| @Override |
| public String getProtocol() { |
| return "snmp"; |
| } |
| |
| /** |
| * Returns the buffer size of this SNMP protocol adaptor. |
| * This buffer size is used for both incoming request and outgoing |
| * inform requests. |
| * By default, buffer size 1024 is used. |
| * |
| * @return The buffer size. |
| */ |
| @Override |
| public Integer getBufferSize() { |
| return new Integer(bufferSize) ; |
| } |
| |
| /** |
| * Sets the buffer size of this SNMP protocol adaptor. |
| * This buffer size is used for both incoming request and outgoing |
| * inform requests. |
| * |
| * @param s The buffer size. |
| * |
| * @exception java.lang.IllegalStateException This method has been invoked |
| * while the communicator was <CODE>ONLINE</CODE> or <CODE>STARTING</CODE>. |
| */ |
| @Override |
| public void setBufferSize(Integer s) |
| throws java.lang.IllegalStateException { |
| if ((state == ONLINE) || (state == STARTING)) { |
| throw new IllegalStateException("Stop server before carrying out"+ |
| " this operation"); |
| } |
| bufferSize = s.intValue() ; |
| } |
| |
| /** |
| * Gets the number of times to try sending an inform request before |
| * giving up. |
| * By default, a maximum of 3 tries is used. |
| * @return The maximun number of tries. |
| */ |
| @Override |
| final public int getMaxTries() { |
| return maxTries; |
| } |
| |
| /** |
| * Changes the maximun number of times to try sending an inform |
| * request before giving up. |
| * @param newMaxTries The maximun number of tries. |
| */ |
| @Override |
| final public synchronized void setMaxTries(int newMaxTries) { |
| if (newMaxTries < 0) |
| throw new IllegalArgumentException(); |
| maxTries = newMaxTries; |
| } |
| |
| /** |
| * Gets the timeout to wait for an inform response from the manager. |
| * By default, a timeout of 3 seconds is used. |
| * @return The value of the timeout property. |
| */ |
| @Override |
| final public int getTimeout() { |
| return timeout; |
| } |
| |
| /** |
| * Changes the timeout to wait for an inform response from the manager. |
| * @param newTimeout The timeout (in milliseconds). |
| */ |
| @Override |
| final public synchronized void setTimeout(int newTimeout) { |
| if (newTimeout < 0) |
| throw new IllegalArgumentException(); |
| timeout= newTimeout; |
| } |
| |
| /** |
| * Returns the message factory of this SNMP protocol adaptor. |
| * |
| * @return The factory object. |
| */ |
| @Override |
| public SnmpPduFactory getPduFactory() { |
| return pduFactory ; |
| } |
| |
| /** |
| * Sets the message factory of this SNMP protocol adaptor. |
| * |
| * @param factory The factory object (null means the default factory). |
| */ |
| @Override |
| public void setPduFactory(SnmpPduFactory factory) { |
| if (factory == null) |
| pduFactory = new SnmpPduFactoryBER() ; |
| else |
| pduFactory = factory ; |
| } |
| |
| /** |
| * Set the user-data factory of this SNMP protocol adaptor. |
| * |
| * @param factory The factory object (null means no factory). |
| * @see com.sun.jmx.snmp.agent.SnmpUserDataFactory |
| */ |
| @Override |
| public void setUserDataFactory(SnmpUserDataFactory factory) { |
| userDataFactory = factory ; |
| } |
| |
| /** |
| * Get the user-data factory associated with this SNMP protocol adaptor. |
| * |
| * @return The factory object (null means no factory). |
| * @see com.sun.jmx.snmp.agent.SnmpUserDataFactory |
| */ |
| @Override |
| public SnmpUserDataFactory getUserDataFactory() { |
| return userDataFactory; |
| } |
| |
| /** |
| * Returns <CODE>true</CODE> if authentication traps are enabled. |
| * <P> |
| * When this feature is enabled, the SNMP protocol adaptor sends |
| * an <CODE>authenticationFailure</CODE> trap each time an |
| * authentication fails. |
| * <P> |
| * The default behaviour is to send authentication traps. |
| * |
| * @return <CODE>true</CODE> if authentication traps are enabled, |
| * <CODE>false</CODE> otherwise. |
| */ |
| @Override |
| public boolean getAuthTrapEnabled() { |
| return authTrapEnabled ; |
| } |
| |
| /** |
| * Sets the flag indicating if traps need to be sent in case of |
| * authentication failure. |
| * |
| * @param enabled Flag indicating if traps need to be sent. |
| */ |
| @Override |
| public void setAuthTrapEnabled(boolean enabled) { |
| authTrapEnabled = enabled ; |
| } |
| |
| /** |
| * Returns <code>true</code> if this SNMP protocol adaptor sends a |
| * response in case of authentication failure. |
| * <P> |
| * When this feature is enabled, the SNMP protocol adaptor sends a |
| * response with <CODE>noSuchName</CODE> or <CODE>readOnly</CODE> when |
| * the authentication failed. If the flag is disabled, the |
| * SNMP protocol adaptor trashes the PDU silently. |
| * <P> |
| * The default behavior is to send responses. |
| * |
| * @return <CODE>true</CODE> if responses are sent. |
| */ |
| @Override |
| public boolean getAuthRespEnabled() { |
| return authRespEnabled ; |
| } |
| |
| /** |
| * Sets the flag indicating if responses need to be sent in case of |
| * authentication failure. |
| * |
| * @param enabled Flag indicating if responses need to be sent. |
| */ |
| @Override |
| public void setAuthRespEnabled(boolean enabled) { |
| authRespEnabled = enabled ; |
| } |
| |
| /** |
| * Returns the enterprise OID. It is used by |
| * {@link #snmpV1Trap snmpV1Trap} to fill the 'enterprise' field of the |
| * trap request. |
| * |
| * @return The OID in string format "x.x.x.x". |
| */ |
| @Override |
| public String getEnterpriseOid() { |
| return enterpriseOid.toString() ; |
| } |
| |
| /** |
| * Sets the enterprise OID. |
| * |
| * @param oid The OID in string format "x.x.x.x". |
| * |
| * @exception IllegalArgumentException The string format is incorrect |
| */ |
| @Override |
| public void setEnterpriseOid(String oid) throws IllegalArgumentException { |
| enterpriseOid = new SnmpOid(oid) ; |
| } |
| |
| /** |
| * Returns the names of the MIBs available in this SNMP protocol adaptor. |
| * |
| * @return An array of MIB names. |
| */ |
| @Override |
| public String[] getMibs() { |
| String[] result = new String[mibs.size()] ; |
| int i = 0 ; |
| for (Enumeration<SnmpMibAgent> e = mibs.elements() ; e.hasMoreElements() ;) { |
| SnmpMibAgent mib = e.nextElement() ; |
| result[i++] = mib.getMibName(); |
| } |
| return result ; |
| } |
| |
| // GETTERS FOR SNMP GROUP (MIBII) |
| //------------------------------- |
| |
| /** |
| * Returns the <CODE>snmpOutTraps</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpOutTraps</CODE> value. |
| */ |
| @Override |
| public Long getSnmpOutTraps() { |
| return new Long(snmpOutTraps); |
| } |
| |
| /** |
| * Returns the <CODE>snmpOutGetResponses</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpOutGetResponses</CODE> value. |
| */ |
| @Override |
| public Long getSnmpOutGetResponses() { |
| return new Long(snmpOutGetResponses); |
| } |
| |
| /** |
| * Returns the <CODE>snmpOutGenErrs</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpOutGenErrs</CODE> value. |
| */ |
| @Override |
| public Long getSnmpOutGenErrs() { |
| return new Long(snmpOutGenErrs); |
| } |
| |
| /** |
| * Returns the <CODE>snmpOutBadValues</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpOutBadValues</CODE> value. |
| */ |
| @Override |
| public Long getSnmpOutBadValues() { |
| return new Long(snmpOutBadValues); |
| } |
| |
| /** |
| * Returns the <CODE>snmpOutNoSuchNames</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpOutNoSuchNames</CODE> value. |
| */ |
| @Override |
| public Long getSnmpOutNoSuchNames() { |
| return new Long(snmpOutNoSuchNames); |
| } |
| |
| /** |
| * Returns the <CODE>snmpOutTooBigs</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpOutTooBigs</CODE> value. |
| */ |
| @Override |
| public Long getSnmpOutTooBigs() { |
| return new Long(snmpOutTooBigs); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInASNParseErrs</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpInASNParseErrs</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInASNParseErrs() { |
| return new Long(snmpInASNParseErrs); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInBadCommunityUses</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpInBadCommunityUses</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInBadCommunityUses() { |
| return new Long(snmpInBadCommunityUses); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInBadCommunityNames</CODE> value defined in |
| * MIB-II. |
| * |
| * @return The <CODE>snmpInBadCommunityNames</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInBadCommunityNames() { |
| return new Long(snmpInBadCommunityNames); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInBadVersions</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpInBadVersions</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInBadVersions() { |
| return new Long(snmpInBadVersions); |
| } |
| |
| /** |
| * Returns the <CODE>snmpOutPkts</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpOutPkts</CODE> value. |
| */ |
| @Override |
| public Long getSnmpOutPkts() { |
| return new Long(snmpOutPkts); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInPkts</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpInPkts</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInPkts() { |
| return new Long(snmpInPkts); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInGetRequests</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpInGetRequests</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInGetRequests() { |
| return new Long(snmpInGetRequests); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInGetNexts</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpInGetNexts</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInGetNexts() { |
| return new Long(snmpInGetNexts); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInSetRequests</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpInSetRequests</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInSetRequests() { |
| return new Long(snmpInSetRequests); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInTotalSetVars</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpInTotalSetVars</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInTotalSetVars() { |
| return new Long(snmpInTotalSetVars); |
| } |
| |
| /** |
| * Returns the <CODE>snmpInTotalReqVars</CODE> value defined in MIB-II. |
| * |
| * @return The <CODE>snmpInTotalReqVars</CODE> value. |
| */ |
| @Override |
| public Long getSnmpInTotalReqVars() { |
| return new Long(snmpInTotalReqVars); |
| } |
| |
| /** |
| * Returns the <CODE>snmpSilentDrops</CODE> value defined in RFC |
| * 1907 NMPv2-MIB . |
| * |
| * @return The <CODE>snmpSilentDrops</CODE> value. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public Long getSnmpSilentDrops() { |
| return new Long(snmpSilentDrops); |
| } |
| |
| /** |
| * Returns the <CODE>snmpProxyDrops</CODE> value defined in RFC |
| * 1907 NMPv2-MIB . |
| * |
| * @return The <CODE>snmpProxyDrops</CODE> value. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public Long getSnmpProxyDrops() { |
| return new Long(0); |
| } |
| |
| |
| // PUBLIC METHODS |
| //--------------- |
| |
| /** |
| * Allows the MBean to perform any operations it needs before being |
| * registered in the MBean server. |
| * If the name of the SNMP protocol adaptor MBean is not specified, |
| * it is initialized with the default value: |
| * {@link com.sun.jmx.snmp.ServiceName#DOMAIN |
| * com.sun.jmx.snmp.ServiceName.DOMAIN}:{@link |
| * com.sun.jmx.snmp.ServiceName#SNMP_ADAPTOR_SERVER |
| * com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_SERVER}. |
| * If any exception is raised, the SNMP protocol adaptor MBean will |
| * not be registered in the MBean server. |
| * |
| * @param server The MBean server to register the service with. |
| * @param name The object name. |
| * |
| * @return The name of the SNMP protocol adaptor registered. |
| * |
| * @exception java.lang.Exception |
| */ |
| @Override |
| public ObjectName preRegister(MBeanServer server, ObjectName name) |
| throws java.lang.Exception { |
| |
| if (name == null) { |
| name = new ObjectName(server.getDefaultDomain() + ":" + |
| com.sun.jmx.snmp.ServiceName.SNMP_ADAPTOR_SERVER); |
| } |
| return (super.preRegister(server, name)); |
| } |
| |
| /** |
| * Not used in this context. |
| */ |
| @Override |
| public void postRegister (Boolean registrationDone) { |
| super.postRegister(registrationDone); |
| } |
| |
| /** |
| * Not used in this context. |
| */ |
| @Override |
| public void preDeregister() throws java.lang.Exception { |
| super.preDeregister(); |
| } |
| |
| /** |
| * Not used in this context. |
| */ |
| @Override |
| public void postDeregister() { |
| super.postDeregister(); |
| } |
| |
| /** |
| * Adds a new MIB in the SNMP MIB handler. |
| * |
| * @param mib The MIB to add. |
| * |
| * @return A reference to the SNMP MIB handler. |
| * |
| * @exception IllegalArgumentException If the parameter is null. |
| */ |
| @Override |
| public SnmpMibHandler addMib(SnmpMibAgent mib) |
| throws IllegalArgumentException { |
| if (mib == null) { |
| throw new IllegalArgumentException() ; |
| } |
| |
| if(!mibs.contains(mib)) |
| mibs.addElement(mib); |
| |
| root.register(mib); |
| |
| return this; |
| } |
| |
| /** |
| * Adds a new MIB in the SNMP MIB handler. |
| * This method is to be called to set a specific agent to a specific OID. |
| * This can be useful when dealing with MIB overlapping. |
| * Some OID can be implemented in more than one MIB. In this case, |
| * the OID nearer agent will be used on SNMP operations. |
| * |
| * @param mib The MIB to add. |
| * @param oids The set of OIDs this agent implements. |
| * |
| * @return A reference to the SNMP MIB handler. |
| * |
| * @exception IllegalArgumentException If the parameter is null. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public SnmpMibHandler addMib(SnmpMibAgent mib, SnmpOid[] oids) |
| throws IllegalArgumentException { |
| if (mib == null) { |
| throw new IllegalArgumentException() ; |
| } |
| |
| //If null oid array, just add it to the mib. |
| if(oids == null) |
| return addMib(mib); |
| |
| if(!mibs.contains(mib)) |
| mibs.addElement(mib); |
| |
| for (int i = 0; i < oids.length; i++) { |
| root.register(mib, oids[i].longValue()); |
| } |
| return this; |
| } |
| |
| /** |
| * Adds a new MIB in the SNMP MIB handler. In SNMP V1 and V2 the |
| * <CODE>contextName</CODE> is useless and this method |
| * is equivalent to <CODE>addMib(SnmpMibAgent mib)</CODE>. |
| * |
| * @param mib The MIB to add. |
| * @param contextName The MIB context name. |
| * @return A reference on the SNMP MIB handler. |
| * |
| * @exception IllegalArgumentException If the parameter is null. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public SnmpMibHandler addMib(SnmpMibAgent mib, String contextName) |
| throws IllegalArgumentException { |
| return addMib(mib); |
| } |
| |
| /** |
| * Adds a new MIB in the SNMP MIB handler. In SNMP V1 and V2 the |
| * <CODE>contextName</CODE> is useless and this method |
| * is equivalent to <CODE>addMib(SnmpMibAgent mib, SnmpOid[] oids)</CODE>. |
| * |
| * @param mib The MIB to add. |
| * @param contextName The MIB context. If null is passed, will be |
| * registered in the default context. |
| * @param oids The set of OIDs this agent implements. |
| * |
| * @return A reference to the SNMP MIB handler. |
| * |
| * @exception IllegalArgumentException If the parameter is null. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public SnmpMibHandler addMib(SnmpMibAgent mib, |
| String contextName, |
| SnmpOid[] oids) |
| throws IllegalArgumentException { |
| |
| return addMib(mib, oids); |
| } |
| |
| /** |
| * Removes the specified MIB from the SNMP protocol adaptor. |
| * In SNMP V1 and V2 the <CODE>contextName</CODE> is useless and this |
| * method is equivalent to <CODE>removeMib(SnmpMibAgent mib)</CODE>. |
| * |
| * @param mib The MIB to be removed. |
| * @param contextName The context name used at registration time. |
| * |
| * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was |
| * a MIB included in the SNMP MIB handler, <CODE>false</CODE> |
| * otherwise. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public boolean removeMib(SnmpMibAgent mib, String contextName) { |
| return removeMib(mib); |
| } |
| |
| /** |
| * Removes the specified MIB from the SNMP protocol adaptor. |
| * |
| * @param mib The MIB to be removed. |
| * |
| * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was a MIB |
| * included in the SNMP MIB handler, <CODE>false</CODE> otherwise. |
| */ |
| @Override |
| public boolean removeMib(SnmpMibAgent mib) { |
| root.unregister(mib); |
| return (mibs.removeElement(mib)) ; |
| } |
| |
| /** |
| * Removes the specified MIB from the SNMP protocol adaptor. |
| * |
| * @param mib The MIB to be removed. |
| * @param oids The oid the MIB was previously registered for. |
| * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was |
| * a MIB included in the SNMP MIB handler, <CODE>false</CODE> |
| * otherwise. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public boolean removeMib(SnmpMibAgent mib, SnmpOid[] oids) { |
| root.unregister(mib, oids); |
| return (mibs.removeElement(mib)) ; |
| } |
| |
| /** |
| * Removes the specified MIB from the SNMP protocol adaptor. |
| * |
| * @param mib The MIB to be removed. |
| * @param contextName The context name used at registration time. |
| * @param oids The oid the MIB was previously registered for. |
| * @return <CODE>true</CODE> if the specified <CODE>mib</CODE> was |
| * a MIB included in the SNMP MIB handler, <CODE>false</CODE> |
| * otherwise. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public boolean removeMib(SnmpMibAgent mib, |
| String contextName, |
| SnmpOid[] oids) { |
| return removeMib(mib, oids); |
| } |
| |
| // SUBCLASSING OF COMMUNICATOR SERVER |
| //----------------------------------- |
| |
| /** |
| * Creates the datagram socket. |
| */ |
| @Override |
| protected void doBind() |
| throws CommunicationException, InterruptedException { |
| |
| try { |
| synchronized (this) { |
| socket = new DatagramSocket(port, address) ; |
| } |
| dbgTag = makeDebugTag(); |
| } catch (SocketException e) { |
| if (e.getMessage().equals(InterruptSysCallMsg)) |
| throw new InterruptedException(e.toString()) ; |
| else { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "doBind", "cannot bind on port " + port); |
| } |
| throw new CommunicationException(e) ; |
| } |
| } |
| } |
| |
| /** |
| * Return the actual port to which the adaptor is bound. |
| * Can be different from the port given at construction time if |
| * that port number was 0. |
| * @return the actual port to which the adaptor is bound. |
| **/ |
| @Override |
| public int getPort() { |
| synchronized (this) { |
| if (socket != null) return socket.getLocalPort(); |
| } |
| return super.getPort(); |
| } |
| |
| /** |
| * Closes the datagram socket. |
| */ |
| @Override |
| protected void doUnbind() |
| throws CommunicationException, InterruptedException { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "doUnbind","Finally close the socket"); |
| } |
| synchronized (this) { |
| if (socket != null) { |
| socket.close() ; |
| socket = null ; |
| // Important to inform finalize() that the socket is closed... |
| } |
| } |
| closeTrapSocketIfNeeded() ; |
| closeInformSocketIfNeeded() ; |
| } |
| |
| private void createSnmpRequestHandler(SnmpAdaptorServer server, |
| int id, |
| DatagramSocket s, |
| DatagramPacket p, |
| SnmpMibTree tree, |
| Vector<SnmpMibAgent> m, |
| InetAddressAcl a, |
| SnmpPduFactory factory, |
| SnmpUserDataFactory dataFactory, |
| MBeanServer f, |
| ObjectName n) { |
| final SnmpRequestHandler handler = |
| new SnmpRequestHandler(this, id, s, p, tree, m, a, factory, |
| dataFactory, f, n); |
| threadService.submitTask(handler); |
| } |
| |
| /** |
| * Reads a packet from the datagram socket and creates a request |
| * handler which decodes and processes the request. |
| */ |
| @Override |
| protected void doReceive() |
| throws CommunicationException, InterruptedException { |
| |
| // Let's wait for something to be received. |
| // |
| try { |
| packet = new DatagramPacket(new byte[bufferSize], bufferSize) ; |
| socket.receive(packet); |
| int state = getState(); |
| |
| if(state != ONLINE) { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "doReceive","received a message but state not online, returning."); |
| } |
| return; |
| } |
| |
| createSnmpRequestHandler(this, servedClientCount, socket, |
| packet, root, mibs, ipacl, pduFactory, |
| userDataFactory, topMBS, objectName); |
| } catch (SocketException e) { |
| // Let's check if we have been interrupted by stop(). |
| // |
| if (e.getMessage().equals(InterruptSysCallMsg)) |
| throw new InterruptedException(e.toString()) ; |
| else |
| throw new CommunicationException(e) ; |
| } catch (InterruptedIOException e) { |
| throw new InterruptedException(e.toString()) ; |
| } catch (CommunicationException e) { |
| throw e ; |
| } catch (Exception e) { |
| throw new CommunicationException(e) ; |
| } |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "doReceive", "received a message"); |
| } |
| } |
| |
| @Override |
| protected void doError(Exception e) throws CommunicationException { |
| } |
| |
| /** |
| * Not used in this context. |
| */ |
| @Override |
| protected void doProcess() |
| throws CommunicationException, InterruptedException { |
| } |
| |
| |
| /** |
| * The number of times the communicator server will attempt |
| * to bind before giving up. |
| * We attempt only once... |
| * @return 1 |
| **/ |
| @Override |
| protected int getBindTries() { |
| return 1; |
| } |
| |
| /** |
| * Stops this SNMP protocol adaptor. |
| * Closes the datagram socket. |
| * <p> |
| * Has no effect if this SNMP protocol adaptor is <CODE>OFFLINE</CODE> or |
| * <CODE>STOPPING</CODE>. |
| */ |
| @Override |
| public void stop(){ |
| |
| final int port = getPort(); |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "stop", "Stopping: using port " + port); |
| } |
| if ((state == ONLINE) || (state == STARTING)){ |
| super.stop(); |
| try { |
| DatagramSocket sn = new DatagramSocket(0); |
| try { |
| byte[] ob = new byte[1]; |
| |
| DatagramPacket pk; |
| if (address != null) |
| pk = new DatagramPacket(ob , 1, address, port); |
| else |
| pk = new DatagramPacket(ob , 1, |
| java.net.InetAddress.getLocalHost(), port); |
| |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "stop", "Sending: using port " + port); |
| } |
| sn.send(pk); |
| } finally { |
| sn.close(); |
| } |
| } catch (Throwable e){ |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "stop", "Got unexpected Throwable", e); |
| } |
| } |
| } |
| } |
| |
| // SENDING SNMP TRAPS STUFF |
| //------------------------- |
| |
| /** |
| * Sends a trap using SNMP V1 trap format. |
| * <BR>The trap is sent to each destination defined in the ACL file |
| * (if available). |
| * If no ACL file or no destinations are available, the trap is sent |
| * to the local host. |
| * |
| * @param generic The generic number of the trap. |
| * @param specific The specific number of the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit defined |
| * by <CODE>bufferSize</CODE>. |
| */ |
| @Override |
| public void snmpV1Trap(int generic, int specific, |
| SnmpVarBindList varBindList) |
| throws IOException, SnmpStatusException { |
| |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "snmpV1Trap", "generic=" + generic + |
| ", specific=" + specific); |
| } |
| |
| // First, make an SNMP V1 trap pdu |
| // |
| SnmpPduTrap pdu = new SnmpPduTrap() ; |
| pdu.address = null ; |
| pdu.port = trapPort ; |
| pdu.type = pduV1TrapPdu ; |
| pdu.version = snmpVersionOne ; |
| pdu.community = null ; |
| pdu.enterprise = enterpriseOid ; |
| pdu.genericTrap = generic ; |
| pdu.specificTrap = specific ; |
| pdu.timeStamp = getSysUpTime(); |
| |
| if (varBindList != null) { |
| pdu.varBindList = new SnmpVarBind[varBindList.size()] ; |
| varBindList.copyInto(pdu.varBindList); |
| } |
| else |
| pdu.varBindList = null ; |
| |
| // If the local host cannot be determined, we put 0.0.0.0 in agentAddr |
| try { |
| if (address != null) |
| pdu.agentAddr = handleMultipleIpVersion(address.getAddress()); |
| else pdu.agentAddr = |
| handleMultipleIpVersion(InetAddress.getLocalHost().getAddress()); |
| } catch (UnknownHostException e) { |
| byte[] zeroedAddr = new byte[4]; |
| pdu.agentAddr = handleMultipleIpVersion(zeroedAddr) ; |
| } |
| |
| // Next, send the pdu to all destinations defined in ACL |
| // |
| sendTrapPdu(pdu) ; |
| } |
| |
| private SnmpIpAddress handleMultipleIpVersion(byte[] address) { |
| if(address.length == 4) |
| return new SnmpIpAddress(address); |
| else { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "handleMultipleIPVersion", |
| "Not an IPv4 address, return null"); |
| } |
| return null; |
| } |
| } |
| |
| /** |
| * Sends a trap using SNMP V1 trap format. |
| * <BR>The trap is sent to the specified <CODE>InetAddress</CODE> |
| * destination using the specified community string (and the ACL file |
| * is not used). |
| * |
| * @param addr The <CODE>InetAddress</CODE> destination of the trap. |
| * @param cs The community string to be used for the trap. |
| * @param generic The generic number of the trap. |
| * @param specific The specific number of the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit defined |
| * by <CODE>bufferSize</CODE>. |
| */ |
| @Override |
| public void snmpV1Trap(InetAddress addr, String cs, int generic, |
| int specific, SnmpVarBindList varBindList) |
| throws IOException, SnmpStatusException { |
| |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "snmpV1Trap", "generic=" + generic + ", specific=" + |
| specific); |
| } |
| |
| // First, make an SNMP V1 trap pdu |
| // |
| SnmpPduTrap pdu = new SnmpPduTrap() ; |
| pdu.address = null ; |
| pdu.port = trapPort ; |
| pdu.type = pduV1TrapPdu ; |
| pdu.version = snmpVersionOne ; |
| |
| if(cs != null) |
| pdu.community = cs.getBytes(); |
| else |
| pdu.community = null ; |
| |
| pdu.enterprise = enterpriseOid ; |
| pdu.genericTrap = generic ; |
| pdu.specificTrap = specific ; |
| pdu.timeStamp = getSysUpTime(); |
| |
| if (varBindList != null) { |
| pdu.varBindList = new SnmpVarBind[varBindList.size()] ; |
| varBindList.copyInto(pdu.varBindList); |
| } |
| else |
| pdu.varBindList = null ; |
| |
| // If the local host cannot be determined, we put 0.0.0.0 in agentAddr |
| try { |
| if (address != null) |
| pdu.agentAddr = handleMultipleIpVersion(address.getAddress()); |
| else pdu.agentAddr = |
| handleMultipleIpVersion(InetAddress.getLocalHost().getAddress()); |
| } catch (UnknownHostException e) { |
| byte[] zeroedAddr = new byte[4]; |
| pdu.agentAddr = handleMultipleIpVersion(zeroedAddr) ; |
| } |
| |
| // Next, send the pdu to the specified destination |
| // |
| if(addr != null) |
| sendTrapPdu(addr, pdu) ; |
| else |
| sendTrapPdu(pdu); |
| } |
| |
| /** |
| * Sends a trap using SNMP V1 trap format. |
| * <BR>The trap is sent to the specified <CODE>InetAddress</CODE> |
| * destination using the specified parameters (and the ACL file is not |
| * used). |
| * Note that if the specified <CODE>InetAddress</CODE> destination is null, |
| * then the ACL file mechanism is used. |
| * |
| * @param addr The <CODE>InetAddress</CODE> destination of the trap. |
| * @param agentAddr The agent address to be used for the trap. |
| * @param cs The community string to be used for the trap. |
| * @param enterpOid The enterprise OID to be used for the trap. |
| * @param generic The generic number of the trap. |
| * @param specific The specific number of the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * @param time The time stamp (overwrite the current time). |
| * |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit defined |
| * by <CODE>bufferSize</CODE>. |
| * |
| * @since 1.5 |
| */ |
| public void snmpV1Trap(InetAddress addr, |
| SnmpIpAddress agentAddr, |
| String cs, |
| SnmpOid enterpOid, |
| int generic, |
| int specific, |
| SnmpVarBindList varBindList, |
| SnmpTimeticks time) |
| throws IOException, SnmpStatusException { |
| snmpV1Trap(addr, |
| trapPort, |
| agentAddr, |
| cs, |
| enterpOid, |
| generic, |
| specific, |
| varBindList, |
| time); |
| } |
| |
| /** |
| * Sends a trap using SNMP V1 trap format. |
| * <BR>The trap is sent to the specified <CODE>SnmpPeer</CODE> destination. |
| * The community string used is the one located in the |
| * <CODE>SnmpPeer</CODE> parameters |
| * (<CODE>SnmpParameters.getRdCommunity() </CODE>). |
| * |
| * @param peer The <CODE>SnmpPeer</CODE> destination of the trap. |
| * @param agentAddr The agent address to be used for the trap. |
| * @param enterpOid The enterprise OID to be used for the trap. |
| * @param generic The generic number of the trap. |
| * @param specific The specific number of the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * @param time The time stamp (overwrite the current time). |
| * |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit |
| * defined by <CODE>bufferSize</CODE>. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public void snmpV1Trap(SnmpPeer peer, |
| SnmpIpAddress agentAddr, |
| SnmpOid enterpOid, |
| int generic, |
| int specific, |
| SnmpVarBindList varBindList, |
| SnmpTimeticks time) |
| throws IOException, SnmpStatusException { |
| |
| SnmpParameters p = (SnmpParameters) peer.getParams(); |
| snmpV1Trap(peer.getDestAddr(), |
| peer.getDestPort(), |
| agentAddr, |
| p.getRdCommunity(), |
| enterpOid, |
| generic, |
| specific, |
| varBindList, |
| time); |
| } |
| |
| private void snmpV1Trap(InetAddress addr, |
| int port, |
| SnmpIpAddress agentAddr, |
| String cs, |
| SnmpOid enterpOid, |
| int generic, |
| int specific, |
| SnmpVarBindList varBindList, |
| SnmpTimeticks time) |
| throws IOException, SnmpStatusException { |
| |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "snmpV1Trap", "generic=" + generic + ", specific=" + |
| specific); |
| } |
| |
| // First, make an SNMP V1 trap pdu |
| // |
| SnmpPduTrap pdu = new SnmpPduTrap() ; |
| pdu.address = null ; |
| pdu.port = port ; |
| pdu.type = pduV1TrapPdu ; |
| pdu.version = snmpVersionOne ; |
| |
| //Diff start |
| if(cs != null) |
| pdu.community = cs.getBytes(); |
| else |
| pdu.community = null ; |
| //Diff end |
| |
| // Diff start |
| if(enterpOid != null) |
| pdu.enterprise = enterpOid; |
| else |
| pdu.enterprise = enterpriseOid ; |
| //Diff end |
| pdu.genericTrap = generic ; |
| pdu.specificTrap = specific ; |
| //Diff start |
| if(time != null) |
| pdu.timeStamp = time.longValue(); |
| else |
| pdu.timeStamp = getSysUpTime(); |
| //Diff end |
| |
| if (varBindList != null) { |
| pdu.varBindList = new SnmpVarBind[varBindList.size()] ; |
| varBindList.copyInto(pdu.varBindList); |
| } |
| else |
| pdu.varBindList = null ; |
| |
| if (agentAddr == null) { |
| // If the local host cannot be determined, |
| // we put 0.0.0.0 in agentAddr |
| try { |
| final InetAddress inetAddr = |
| (address!=null)?address:InetAddress.getLocalHost(); |
| agentAddr = handleMultipleIpVersion(inetAddr.getAddress()); |
| } catch (UnknownHostException e) { |
| byte[] zeroedAddr = new byte[4]; |
| agentAddr = handleMultipleIpVersion(zeroedAddr); |
| } |
| } |
| |
| pdu.agentAddr = agentAddr; |
| |
| // Next, send the pdu to the specified destination |
| // |
| // Diff start |
| if(addr != null) |
| sendTrapPdu(addr, pdu) ; |
| else |
| sendTrapPdu(pdu); |
| |
| //End diff |
| } |
| |
| /** |
| * Sends a trap using SNMP V2 trap format. |
| * <BR>The trap is sent to the specified <CODE>SnmpPeer</CODE> destination. |
| * <BR>The community string used is the one located in the |
| * <CODE>SnmpPeer</CODE> parameters |
| * (<CODE>SnmpParameters.getRdCommunity() </CODE>). |
| * <BR>The variable list included in the outgoing trap is composed of |
| * the following items: |
| * <UL> |
| * <LI><CODE>sysUpTime.0</CODE> with the value specified by |
| * <CODE>time</CODE></LI> |
| * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by |
| * <CODE>trapOid</CODE></LI> |
| * <LI><CODE>all the (oid,values)</CODE> from the specified |
| * <CODE>varBindList</CODE></LI> |
| * </UL> |
| * |
| * @param peer The <CODE>SnmpPeer</CODE> destination of the trap. |
| * @param trapOid The OID identifying the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * @param time The time stamp (overwrite the current time). |
| * |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit |
| * defined by <CODE>bufferSize</CODE>. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public void snmpV2Trap(SnmpPeer peer, |
| SnmpOid trapOid, |
| SnmpVarBindList varBindList, |
| SnmpTimeticks time) |
| throws IOException, SnmpStatusException { |
| |
| SnmpParameters p = (SnmpParameters) peer.getParams(); |
| snmpV2Trap(peer.getDestAddr(), |
| peer.getDestPort(), |
| p.getRdCommunity(), |
| trapOid, |
| varBindList, |
| time); |
| } |
| |
| /** |
| * Sends a trap using SNMP V2 trap format. |
| * <BR>The trap is sent to each destination defined in the ACL file |
| * (if available). If no ACL file or no destinations are available, |
| * the trap is sent to the local host. |
| * <BR>The variable list included in the outgoing trap is composed of |
| * the following items: |
| * <UL> |
| * <LI><CODE>sysUpTime.0</CODE> with its current value</LI> |
| * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by |
| * <CODE>trapOid</CODE></LI> |
| * <LI><CODE>all the (oid,values)</CODE> from the specified |
| * <CODE>varBindList</CODE></LI> |
| * </UL> |
| * |
| * @param trapOid The OID identifying the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit defined |
| * by <CODE>bufferSize</CODE>. |
| */ |
| @Override |
| public void snmpV2Trap(SnmpOid trapOid, SnmpVarBindList varBindList) |
| throws IOException, SnmpStatusException { |
| |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "snmpV2Trap", "trapOid=" + trapOid); |
| } |
| |
| // First, make an SNMP V2 trap pdu |
| // We clone varBindList and insert sysUpTime and snmpTrapOid |
| // |
| SnmpPduRequest pdu = new SnmpPduRequest() ; |
| pdu.address = null ; |
| pdu.port = trapPort ; |
| pdu.type = pduV2TrapPdu ; |
| pdu.version = snmpVersionTwo ; |
| pdu.community = null ; |
| |
| SnmpVarBindList fullVbl ; |
| if (varBindList != null) |
| fullVbl = varBindList.clone() ; |
| else |
| fullVbl = new SnmpVarBindList(2) ; |
| SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ; |
| fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ; |
| fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue), |
| 0); |
| pdu.varBindList = new SnmpVarBind[fullVbl.size()] ; |
| fullVbl.copyInto(pdu.varBindList) ; |
| |
| // Next, send the pdu to all destinations defined in ACL |
| // |
| sendTrapPdu(pdu) ; |
| } |
| |
| /** |
| * Sends a trap using SNMP V2 trap format. |
| * <BR>The trap is sent to the specified <CODE>InetAddress</CODE> |
| * destination using the specified community string (and the ACL file |
| * is not used). |
| * <BR>The variable list included in the outgoing trap is composed of |
| * the following items: |
| * <UL> |
| * <LI><CODE>sysUpTime.0</CODE> with its current value</LI> |
| * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by |
| * <CODE>trapOid</CODE></LI> |
| * <LI><CODE>all the (oid,values)</CODE> from the specified |
| * <CODE>varBindList</CODE></LI> |
| * </UL> |
| * |
| * @param addr The <CODE>InetAddress</CODE> destination of the trap. |
| * @param cs The community string to be used for the trap. |
| * @param trapOid The OID identifying the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit |
| * defined by <CODE>bufferSize</CODE>. |
| */ |
| @Override |
| public void snmpV2Trap(InetAddress addr, String cs, SnmpOid trapOid, |
| SnmpVarBindList varBindList) |
| throws IOException, SnmpStatusException { |
| |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "snmpV2Trap", "trapOid=" + trapOid); |
| } |
| |
| // First, make an SNMP V2 trap pdu |
| // We clone varBindList and insert sysUpTime and snmpTrapOid |
| // |
| SnmpPduRequest pdu = new SnmpPduRequest() ; |
| pdu.address = null ; |
| pdu.port = trapPort ; |
| pdu.type = pduV2TrapPdu ; |
| pdu.version = snmpVersionTwo ; |
| |
| if(cs != null) |
| pdu.community = cs.getBytes(); |
| else |
| pdu.community = null; |
| |
| SnmpVarBindList fullVbl ; |
| if (varBindList != null) |
| fullVbl = varBindList.clone() ; |
| else |
| fullVbl = new SnmpVarBindList(2) ; |
| SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ; |
| fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ; |
| fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue), |
| 0); |
| pdu.varBindList = new SnmpVarBind[fullVbl.size()] ; |
| fullVbl.copyInto(pdu.varBindList) ; |
| |
| // Next, send the pdu to the specified destination |
| // |
| if(addr != null) |
| sendTrapPdu(addr, pdu); |
| else |
| sendTrapPdu(pdu); |
| } |
| |
| /** |
| * Sends a trap using SNMP V2 trap format. |
| * <BR>The trap is sent to the specified <CODE>InetAddress</CODE> |
| * destination using the specified parameters (and the ACL file is not |
| * used). |
| * Note that if the specified <CODE>InetAddress</CODE> destination is null, |
| * then the ACL file mechanism is used. |
| * <BR>The variable list included in the outgoing trap is composed of the |
| * following items: |
| * <UL> |
| * <LI><CODE>sysUpTime.0</CODE> with the value specified by |
| * <CODE>time</CODE></LI> |
| * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by |
| * <CODE>trapOid</CODE></LI> |
| * <LI><CODE>all the (oid,values)</CODE> from the specified |
| * <CODE>varBindList</CODE></LI> |
| * </UL> |
| * |
| * @param addr The <CODE>InetAddress</CODE> destination of the trap. |
| * @param cs The community string to be used for the trap. |
| * @param trapOid The OID identifying the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * @param time The time stamp (overwrite the current time). |
| * |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit |
| * defined by <CODE>bufferSize</CODE>. |
| * |
| * @since 1.5 |
| */ |
| public void snmpV2Trap(InetAddress addr, |
| String cs, |
| SnmpOid trapOid, |
| SnmpVarBindList varBindList, |
| SnmpTimeticks time) |
| throws IOException, SnmpStatusException { |
| |
| snmpV2Trap(addr, |
| trapPort, |
| cs, |
| trapOid, |
| varBindList, |
| time); |
| } |
| |
| private void snmpV2Trap(InetAddress addr, |
| int port, |
| String cs, |
| SnmpOid trapOid, |
| SnmpVarBindList varBindList, |
| SnmpTimeticks time) |
| throws IOException, SnmpStatusException { |
| |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| final StringBuilder strb = new StringBuilder() |
| .append("trapOid=").append(trapOid) |
| .append("\ncommunity=").append(cs) |
| .append("\naddr=").append(addr) |
| .append("\nvarBindList=").append(varBindList) |
| .append("\ntime=").append(time) |
| .append("\ntrapPort=").append(port); |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "snmpV2Trap", strb.toString()); |
| } |
| |
| // First, make an SNMP V2 trap pdu |
| // We clone varBindList and insert sysUpTime and snmpTrapOid |
| // |
| SnmpPduRequest pdu = new SnmpPduRequest() ; |
| pdu.address = null ; |
| pdu.port = port ; |
| pdu.type = pduV2TrapPdu ; |
| pdu.version = snmpVersionTwo ; |
| |
| if(cs != null) |
| pdu.community = cs.getBytes(); |
| else |
| pdu.community = null; |
| |
| SnmpVarBindList fullVbl ; |
| if (varBindList != null) |
| fullVbl = varBindList.clone() ; |
| else |
| fullVbl = new SnmpVarBindList(2) ; |
| |
| // Only difference with other |
| SnmpTimeticks sysUpTimeValue; |
| if(time != null) |
| sysUpTimeValue = time; |
| else |
| sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ; |
| //End of diff |
| |
| fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ; |
| fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue), |
| 0); |
| pdu.varBindList = new SnmpVarBind[fullVbl.size()] ; |
| fullVbl.copyInto(pdu.varBindList) ; |
| |
| // Next, send the pdu to the specified destination |
| // |
| // Diff start |
| if(addr != null) |
| sendTrapPdu(addr, pdu) ; |
| else |
| sendTrapPdu(pdu); |
| //End diff |
| } |
| |
| /** |
| * Send the specified trap PDU to the passed <CODE>InetAddress</CODE>. |
| * @param address The destination address. |
| * @param pdu The pdu to send. |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit |
| * defined by <CODE>bufferSize</CODE>. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public void snmpPduTrap(InetAddress address, SnmpPduPacket pdu) |
| throws IOException, SnmpStatusException { |
| |
| if(address != null) |
| sendTrapPdu(address, pdu); |
| else |
| sendTrapPdu(pdu); |
| } |
| |
| /** |
| * Send the specified trap PDU to the passed <CODE>SnmpPeer</CODE>. |
| * @param peer The destination peer. The Read community string is used of |
| * <CODE>SnmpParameters</CODE> is used as the trap community string. |
| * @param pdu The pdu to send. |
| * @exception IOException An I/O error occurred while sending the trap. |
| * @exception SnmpStatusException If the trap exceeds the limit defined |
| * by <CODE>bufferSize</CODE>. |
| * @since 1.5 |
| */ |
| @Override |
| public void snmpPduTrap(SnmpPeer peer, |
| SnmpPduPacket pdu) |
| throws IOException, SnmpStatusException { |
| if(peer != null) { |
| pdu.port = peer.getDestPort(); |
| sendTrapPdu(peer.getDestAddr(), pdu); |
| } |
| else { |
| pdu.port = getTrapPort().intValue(); |
| sendTrapPdu(pdu); |
| } |
| } |
| |
| /** |
| * Send the specified trap PDU to every destinations from the ACL file. |
| */ |
| private void sendTrapPdu(SnmpPduPacket pdu) |
| throws SnmpStatusException, IOException { |
| |
| // Make an SNMP message from the pdu |
| // |
| SnmpMessage msg = null ; |
| try { |
| msg = (SnmpMessage)pduFactory.encodeSnmpPdu(pdu, bufferSize) ; |
| if (msg == null) { |
| throw new SnmpStatusException( |
| SnmpDefinitions.snmpRspAuthorizationError) ; |
| } |
| } |
| catch (SnmpTooBigException x) { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "sendTrapPdu", "Trap pdu is too big. " + |
| "Trap hasn't been sent to anyone" ); |
| } |
| throw new SnmpStatusException(SnmpDefinitions.snmpRspTooBig) ; |
| // FIXME: is the right exception to throw ? |
| // We could simply forward SnmpTooBigException ? |
| } |
| |
| // Now send the SNMP message to each destination |
| // |
| int sendingCount = 0 ; |
| openTrapSocketIfNeeded() ; |
| if (ipacl != null) { |
| Enumeration<InetAddress> ed = ipacl.getTrapDestinations() ; |
| while (ed.hasMoreElements()) { |
| msg.address = ed.nextElement() ; |
| Enumeration<String> ec = ipacl.getTrapCommunities(msg.address) ; |
| while (ec.hasMoreElements()) { |
| msg.community = ec.nextElement().getBytes() ; |
| try { |
| sendTrapMessage(msg) ; |
| sendingCount++ ; |
| } |
| catch (SnmpTooBigException x) { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "sendTrapPdu", "Trap pdu is too big. " + |
| "Trap hasn't been sent to "+msg.address); |
| } |
| } |
| } |
| } |
| } |
| |
| // If there is no destination defined or if everything has failed |
| // we tried to send the trap to the local host (as suggested by |
| // mister Olivier Reisacher). |
| // |
| if (sendingCount == 0) { |
| try { |
| msg.address = InetAddress.getLocalHost() ; |
| sendTrapMessage(msg) ; |
| } catch (SnmpTooBigException x) { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "sendTrapPdu", "Trap pdu is too big. " + |
| "Trap hasn't been sent."); |
| } |
| } catch (UnknownHostException e) { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "sendTrapPdu", "Trap pdu is too big. " + |
| "Trap hasn't been sent."); |
| } |
| } |
| } |
| |
| closeTrapSocketIfNeeded() ; |
| } |
| |
| /** |
| * Send the specified trap PDU to the specified destination. |
| */ |
| private void sendTrapPdu(InetAddress addr, SnmpPduPacket pdu) |
| throws SnmpStatusException, IOException { |
| |
| // Make an SNMP message from the pdu |
| // |
| SnmpMessage msg = null ; |
| try { |
| msg = (SnmpMessage)pduFactory.encodeSnmpPdu(pdu, bufferSize) ; |
| if (msg == null) { |
| throw new SnmpStatusException( |
| SnmpDefinitions.snmpRspAuthorizationError) ; |
| } |
| } catch (SnmpTooBigException x) { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "sendTrapPdu", "Trap pdu is too big. " + |
| "Trap hasn't been sent to the specified host."); |
| } |
| throw new SnmpStatusException(SnmpDefinitions.snmpRspTooBig) ; |
| // FIXME: is the right exception to throw ? |
| // We could simply forward SnmpTooBigException ? |
| } |
| |
| // Now send the SNMP message to specified destination |
| // |
| openTrapSocketIfNeeded() ; |
| if (addr != null) { |
| msg.address = addr; |
| try { |
| sendTrapMessage(msg) ; |
| } catch (SnmpTooBigException x) { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINEST)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, |
| "sendTrapPdu", "Trap pdu is too big. " + |
| "Trap hasn't been sent to " + msg.address); |
| } |
| } |
| } |
| |
| closeTrapSocketIfNeeded() ; |
| } |
| |
| /** |
| * Send the specified message on trapSocket. |
| */ |
| private void sendTrapMessage(SnmpMessage msg) |
| throws IOException, SnmpTooBigException { |
| |
| byte[] buffer = new byte[bufferSize] ; |
| DatagramPacket packet = new DatagramPacket(buffer, buffer.length) ; |
| int encodingLength = msg.encodeMessage(buffer) ; |
| packet.setLength(encodingLength) ; |
| packet.setAddress(msg.address) ; |
| packet.setPort(msg.port) ; |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "sendTrapMessage", "sending trap to " + msg.address + ":" + |
| msg.port); |
| } |
| trapSocket.send(packet) ; |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "sendTrapMessage", "sent to " + msg.address + ":" + |
| msg.port); |
| } |
| snmpOutTraps++; |
| snmpOutPkts++; |
| } |
| |
| /** |
| * Open trapSocket if it's not already done. |
| */ |
| synchronized void openTrapSocketIfNeeded() throws SocketException { |
| if (trapSocket == null) { |
| trapSocket = new DatagramSocket(0, address) ; |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "openTrapSocketIfNeeded", "using port " + |
| trapSocket.getLocalPort() + " to send traps"); |
| } |
| } |
| } |
| |
| /** |
| * Close trapSocket if the SNMP protocol adaptor is not ONLINE. |
| */ |
| synchronized void closeTrapSocketIfNeeded() { |
| if ((trapSocket != null) && (state != ONLINE)) { |
| trapSocket.close() ; |
| trapSocket = null ; |
| } |
| } |
| |
| // SENDING SNMP INFORMS STUFF |
| //--------------------------- |
| |
| /** |
| * Sends an inform using SNMP V2 inform request format. |
| * <BR>The inform request is sent to each destination defined in the ACL |
| * file (if available). |
| * If no ACL file or no destinations are available, the inform request is |
| * sent to the local host. |
| * <BR>The variable list included in the outgoing inform is composed of |
| * the following items: |
| * <UL> |
| * <LI><CODE>sysUpTime.0</CODE> with its current value</LI> |
| * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by |
| * <CODE>trapOid</CODE></LI> |
| * <LI><CODE>all the (oid,values)</CODE> from the specified |
| * <CODE>varBindList</CODE></LI> |
| * </UL> |
| * To send an inform request, the SNMP adaptor server must be active. |
| * |
| * @param cb The callback that is invoked when a request is complete. |
| * @param trapOid The OID identifying the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * |
| * @return A vector of {@link com.sun.jmx.snmp.daemon.SnmpInformRequest} |
| * objects. |
| * <P>If there is no destination host for this inform request, |
| * the returned vector will be empty. |
| * |
| * @exception IllegalStateException This method has been invoked while |
| * the SNMP adaptor server was not active. |
| * @exception IOException An I/O error occurred while sending the |
| * inform request. |
| * @exception SnmpStatusException If the inform request exceeds the |
| * limit defined by <CODE>bufferSize</CODE>. |
| */ |
| @Override |
| public Vector<SnmpInformRequest> snmpInformRequest(SnmpInformHandler cb, |
| SnmpOid trapOid, |
| SnmpVarBindList varBindList) |
| throws IllegalStateException, IOException, SnmpStatusException { |
| |
| if (!isActive()) { |
| throw new IllegalStateException( |
| "Start SNMP adaptor server before carrying out this operation"); |
| } |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "snmpInformRequest", "trapOid=" + trapOid); |
| } |
| |
| // First, make an SNMP inform pdu: |
| // We clone varBindList and insert sysUpTime and snmpTrapOid variables. |
| // |
| SnmpVarBindList fullVbl ; |
| if (varBindList != null) |
| fullVbl = varBindList.clone() ; |
| else |
| fullVbl = new SnmpVarBindList(2) ; |
| SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ; |
| fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ; |
| fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue), |
| 0); |
| |
| // Next, send the pdu to the specified destination |
| // |
| openInformSocketIfNeeded() ; |
| |
| // Now send the SNMP message to each destination |
| // |
| Vector<SnmpInformRequest> informReqList = new Vector<>(); |
| InetAddress addr; |
| String cs; |
| if (ipacl != null) { |
| Enumeration<InetAddress> ed = ipacl.getInformDestinations() ; |
| while (ed.hasMoreElements()) { |
| addr = ed.nextElement() ; |
| Enumeration<String> ec = ipacl.getInformCommunities(addr) ; |
| while (ec.hasMoreElements()) { |
| cs = ec.nextElement() ; |
| informReqList.addElement( |
| informSession.makeAsyncRequest(addr, cs, cb, |
| fullVbl,getInformPort())) ; |
| } |
| } |
| } |
| |
| return informReqList ; |
| } |
| |
| /** |
| * Sends an inform using SNMP V2 inform request format. |
| * <BR>The inform is sent to the specified <CODE>InetAddress</CODE> |
| * destination |
| * using the specified community string. |
| * <BR>The variable list included in the outgoing inform is composed |
| * of the following items: |
| * <UL> |
| * <LI><CODE>sysUpTime.0</CODE> with its current value</LI> |
| * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by |
| * <CODE>trapOid</CODE></LI> |
| * <LI><CODE>all the (oid,values)</CODE> from the specified |
| * <CODE>varBindList</CODE></LI> |
| * </UL> |
| * To send an inform request, the SNMP adaptor server must be active. |
| * |
| * @param addr The <CODE>InetAddress</CODE> destination for this inform |
| * request. |
| * @param cs The community string to be used for the inform request. |
| * @param cb The callback that is invoked when a request is complete. |
| * @param trapOid The OID identifying the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * |
| * @return The inform request object. |
| * |
| * @exception IllegalStateException This method has been invoked |
| * while the SNMP adaptor server was not active. |
| * @exception IOException An I/O error occurred while sending the |
| * inform request. |
| * @exception SnmpStatusException If the inform request exceeds the |
| * limit defined by <CODE>bufferSize</CODE>. |
| */ |
| @Override |
| public SnmpInformRequest snmpInformRequest(InetAddress addr, |
| String cs, |
| SnmpInformHandler cb, |
| SnmpOid trapOid, |
| SnmpVarBindList varBindList) |
| throws IllegalStateException, IOException, SnmpStatusException { |
| |
| return snmpInformRequest(addr, |
| getInformPort(), |
| cs, |
| cb, |
| trapOid, |
| varBindList); |
| } |
| |
| /** |
| * Sends an inform using SNMP V2 inform request format. |
| * <BR>The inform is sent to the specified <CODE>SnmpPeer</CODE> |
| * destination. |
| * <BR>The community string used is the one located in the |
| * <CODE>SnmpPeer</CODE> parameters |
| * (<CODE>SnmpParameters.getInformCommunity() </CODE>). |
| * <BR>The variable list included in the outgoing inform is composed |
| * of the following items: |
| * <UL> |
| * <LI><CODE>sysUpTime.0</CODE> with its current value</LI> |
| * <LI><CODE>snmpTrapOid.0</CODE> with the value specified by |
| * <CODE>trapOid</CODE></LI> |
| * <LI><CODE>all the (oid,values)</CODE> from the specified |
| * <CODE>varBindList</CODE></LI> |
| * </UL> |
| * To send an inform request, the SNMP adaptor server must be active. |
| * |
| * @param peer The <CODE>SnmpPeer</CODE> destination for this inform |
| * request. |
| * @param cb The callback that is invoked when a request is complete. |
| * @param trapOid The OID identifying the trap. |
| * @param varBindList A list of <CODE>SnmpVarBind</CODE> instances or null. |
| * |
| * @return The inform request object. |
| * |
| * @exception IllegalStateException This method has been invoked while |
| * the SNMP adaptor server was not active. |
| * @exception IOException An I/O error occurred while sending the |
| * inform request. |
| * @exception SnmpStatusException If the inform request exceeds the |
| * limit defined by <CODE>bufferSize</CODE>. |
| * |
| * @since 1.5 |
| */ |
| @Override |
| public SnmpInformRequest snmpInformRequest(SnmpPeer peer, |
| SnmpInformHandler cb, |
| SnmpOid trapOid, |
| SnmpVarBindList varBindList) |
| throws IllegalStateException, IOException, SnmpStatusException { |
| |
| SnmpParameters p = (SnmpParameters) peer.getParams(); |
| return snmpInformRequest(peer.getDestAddr(), |
| peer.getDestPort(), |
| p.getInformCommunity(), |
| cb, |
| trapOid, |
| varBindList); |
| } |
| |
| /** |
| * Method that maps an SNMP error status in the passed protocolVersion |
| * according to the provided pdu type. |
| * @param errorStatus The error status to convert. |
| * @param protocolVersion The protocol version. |
| * @param reqPduType The pdu type. |
| */ |
| public static int mapErrorStatus(int errorStatus, |
| int protocolVersion, |
| int reqPduType) { |
| return SnmpSubRequestHandler.mapErrorStatus(errorStatus, |
| protocolVersion, |
| reqPduType); |
| } |
| |
| private SnmpInformRequest snmpInformRequest(InetAddress addr, |
| int port, |
| String cs, |
| SnmpInformHandler cb, |
| SnmpOid trapOid, |
| SnmpVarBindList varBindList) |
| throws IllegalStateException, IOException, SnmpStatusException { |
| |
| if (!isActive()) { |
| throw new IllegalStateException( |
| "Start SNMP adaptor server before carrying out this operation"); |
| } |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "snmpInformRequest", "trapOid=" + trapOid); |
| } |
| |
| // First, make an SNMP inform pdu: |
| // We clone varBindList and insert sysUpTime and snmpTrapOid variables. |
| // |
| SnmpVarBindList fullVbl ; |
| if (varBindList != null) |
| fullVbl = varBindList.clone() ; |
| else |
| fullVbl = new SnmpVarBindList(2) ; |
| SnmpTimeticks sysUpTimeValue = new SnmpTimeticks(getSysUpTime()) ; |
| fullVbl.insertElementAt(new SnmpVarBind(snmpTrapOidOid, trapOid), 0) ; |
| fullVbl.insertElementAt(new SnmpVarBind(sysUpTimeOid, sysUpTimeValue), |
| 0); |
| |
| // Next, send the pdu to the specified destination |
| // |
| openInformSocketIfNeeded() ; |
| return informSession.makeAsyncRequest(addr, cs, cb, fullVbl, port) ; |
| } |
| |
| |
| /** |
| * Open informSocket if it's not already done. |
| */ |
| synchronized void openInformSocketIfNeeded() throws SocketException { |
| if (informSession == null) { |
| informSession = new SnmpSession(this) ; |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "openInformSocketIfNeeded", |
| "to send inform requests and receive inform responses"); |
| } |
| } |
| } |
| |
| /** |
| * Close informSocket if the SNMP protocol adaptor is not ONLINE. |
| */ |
| synchronized void closeInformSocketIfNeeded() { |
| if ((informSession != null) && (state != ONLINE)) { |
| informSession.destroySession() ; |
| informSession = null ; |
| } |
| } |
| |
| /** |
| * Gets the IP address to bind. |
| * This getter is used to initialize the DatagramSocket in the |
| * SnmpSocket object created for the inform request stuff. |
| */ |
| InetAddress getAddress() { |
| return address; |
| } |
| |
| |
| // PROTECTED METHODS |
| //------------------ |
| |
| /** |
| * Finalizer of the SNMP protocol adaptor objects. |
| * This method is called by the garbage collector on an object |
| * when garbage collection determines that there are no more |
| * references to the object. |
| * <P>Closes the datagram socket associated to this SNMP protocol adaptor. |
| */ |
| @Override |
| protected void finalize() { |
| try { |
| if (socket != null) { |
| socket.close() ; |
| socket = null ; |
| } |
| |
| threadService.terminate(); |
| } catch (Exception e) { |
| if (SNMP_ADAPTOR_LOGGER.isLoggable(Level.FINER)) { |
| SNMP_ADAPTOR_LOGGER.logp(Level.FINER, dbgTag, |
| "finalize", "Exception in finalizer", e); |
| } |
| } |
| } |
| |
| // PACKAGE METHODS |
| //---------------- |
| |
| /** |
| * Returns the string used in debug traces. |
| */ |
| @Override |
| String makeDebugTag() { |
| return "SnmpAdaptorServer["+ getProtocol() + ":" + getPort() + "]"; |
| } |
| |
| void updateRequestCounters(int pduType) { |
| switch(pduType) { |
| |
| case pduGetRequestPdu: |
| snmpInGetRequests++; |
| break; |
| case pduGetNextRequestPdu: |
| snmpInGetNexts++; |
| break; |
| case pduSetRequestPdu: |
| snmpInSetRequests++; |
| break; |
| default: |
| break; |
| } |
| snmpInPkts++ ; |
| } |
| |
| void updateErrorCounters(int errorStatus) { |
| switch(errorStatus) { |
| |
| case snmpRspNoError: |
| snmpOutGetResponses++; |
| break; |
| case snmpRspGenErr: |
| snmpOutGenErrs++; |
| break; |
| case snmpRspBadValue: |
| snmpOutBadValues++; |
| break; |
| case snmpRspNoSuchName: |
| snmpOutNoSuchNames++; |
| break; |
| case snmpRspTooBig: |
| snmpOutTooBigs++; |
| break; |
| default: |
| break; |
| } |
| snmpOutPkts++ ; |
| } |
| |
| void updateVarCounters(int pduType, int n) { |
| switch(pduType) { |
| |
| case pduGetRequestPdu: |
| case pduGetNextRequestPdu: |
| case pduGetBulkRequestPdu: |
| snmpInTotalReqVars += n ; |
| break ; |
| case pduSetRequestPdu: |
| snmpInTotalSetVars += n ; |
| break ; |
| } |
| } |
| |
| void incSnmpInASNParseErrs(int n) { |
| snmpInASNParseErrs += n ; |
| } |
| |
| void incSnmpInBadVersions(int n) { |
| snmpInBadVersions += n ; |
| } |
| |
| void incSnmpInBadCommunityUses(int n) { |
| snmpInBadCommunityUses += n ; |
| } |
| |
| void incSnmpInBadCommunityNames(int n) { |
| snmpInBadCommunityNames += n ; |
| } |
| |
| void incSnmpSilentDrops(int n) { |
| snmpSilentDrops += n ; |
| } |
| // PRIVATE METHODS |
| //---------------- |
| |
| /** |
| * Returns the time (in hundreths of second) elapsed since the SNMP |
| * protocol adaptor startup. |
| */ |
| long getSysUpTime() { |
| return (System.currentTimeMillis() - startUpTime) / 10 ; |
| } |
| |
| /** |
| * Control the way the SnmpAdaptorServer service is deserialized. |
| */ |
| private void readObject(ObjectInputStream stream) |
| throws IOException, ClassNotFoundException { |
| |
| // Call the default deserialization of the object. |
| // |
| stream.defaultReadObject(); |
| |
| // Call the specific initialization for the SnmpAdaptorServer service. |
| // This is for transient structures to be initialized to specific |
| // default values. |
| // |
| mibs = new Vector<>() ; |
| } |
| |
| /** |
| * Common initializations. |
| */ |
| private void init(InetAddressAcl acl, int p, InetAddress a) { |
| |
| root= new SnmpMibTree(); |
| |
| // The default Agent is initialized with a SnmpErrorHandlerAgent agent. |
| root.setDefaultAgent(new SnmpErrorHandlerAgent()); |
| |
| // For the trap time, use the time the agent started ... |
| // |
| startUpTime= java.lang.System.currentTimeMillis(); |
| maxActiveClientCount = 10; |
| |
| // Create the default message factory |
| pduFactory = new SnmpPduFactoryBER() ; |
| |
| port = p ; |
| ipacl = acl ; |
| address = a ; |
| |
| if ((ipacl == null) && (useAcl == true)) |
| throw new IllegalArgumentException("ACL object cannot be null") ; |
| |
| threadService = new ThreadService(threadNumber); |
| } |
| |
| SnmpMibAgent getAgentMib(SnmpOid oid) { |
| return root.getAgentMib(oid); |
| } |
| |
| @Override |
| protected Thread createMainThread() { |
| final Thread t = super.createMainThread(); |
| t.setDaemon(true); |
| return t; |
| } |
| |
| } |