/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004-2010], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program 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 for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.snmp; import java.io.IOException; import java.io.File; import java.util.Properties; import org.hyperic.util.collection.IntHashMap; import org.hyperic.util.config.ConfigResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.snmp4j.smi.OID; public class SNMPClient { private static final int VERSION_1 = 1; private static final int VERSION_2C = 2; private static final int VERSION_3 = 3; static final int AUTH_MD5 = 0; static final int AUTH_SHA = 1; public static final String DEFAULT_IP = "127.0.0.1"; public static final int DEFAULT_PORT = 161; public static final String DEFAULT_TRANSPORT = "udp"; public static final String DEFAULT_USERNAME = "username"; public static final String DEFAULT_PASSWORD = ""; public static final String DEFAULT_AUTHTYPE = "none"; public static final String DEFAULT_PRIV_TYPE = "none"; public static final String DEFAULT_PORT_STRING = String.valueOf(DEFAULT_PORT); public static final String DEFAULT_COMMUNITY = System.getProperty("snmp.defaultCommunity", "public"); public static final String DEFAULT_RETRIES = "1"; public static final String DEFAULT_TIMEOUT = "1500"; public static final String[] VALID_VERSIONS = { "v1", "v2c", "v3" }; public static final String PROP_IP = "snmpIp"; public static final String PROP_PORT = "snmpPort"; public static final String PROP_TRANSPORT = "snmpTransport"; public static final String PROP_VERSION = "snmpVersion"; public static final String PROP_COMMUNITY = "snmpCommunity"; public static final String PROP_USER = "snmpUser"; public static final String PROP_PASSWORD = "snmpPassword"; public static final String PROP_AUTHTYPE = "snmpAuthType"; public static final String PROP_PRIV_TYPE = "snmpPrivacyType"; public static final String PROP_PRIV_PASSPHRASE = "snmpPrivacyPassPhrase"; public static final String PROP_SECURITY_CONTEXT = "snmpSecurityContext"; public static final String PROP_RETRIES = "snmpRetries"; public static final String PROP_TIMEOUT = "snmpTimeout"; private static Log log = LogFactory.getLog(SNMPClient.class); // Cache should be configurable by subclasses... private static int CACHE_EXPIRE_DEFAULT = 60 * 5 * 1000; // 5 minutes private static IntHashMap sessionCache = null; private static MIBTree mibTree; private int sessionCacheExpire = CACHE_EXPIRE_DEFAULT; private static int parseVersion(String version) { if (version == null) { throw new IllegalArgumentException("version is null"); } if (version.equalsIgnoreCase("v1")) { return VERSION_1; } else if (version.equalsIgnoreCase("v2c")) { return VERSION_2C; } else if (version.equalsIgnoreCase("v3")) { return VERSION_3; } throw new IllegalArgumentException("unknown version: " + version); } public SNMPClient() { } public void addMIBs(String jar, String[] accept) { try { mibTree.parse(new File(jar), accept); } catch (IOException e) { log.error(e.getMessage(), e); } } public void addMIBs(String[] mibs) { for (int i = 0; i < mibs.length; i++) { File file = new File(mibs[i]); if (file.exists()) { try { mibTree.parse(file); } catch (IOException e) { log.error(e.getMessage(), e); } } else { log.debug("MIB '" + file + "' does not exist"); } } } static synchronized OID getMibOID(String mibName) throws MIBLookupException { int[] oid = mibTree.getOID(mibName); if (oid == null) { String msg = "Failed to lookup MIB for name=" + mibName; String unfound = mibTree.getLastLookupFailure(); if (!mibName.equals(unfound)) { msg += " (last lookup failure=" + unfound + ")"; } throw new MIBLookupException(msg); } return new OID(oid); } public static String getOID(String mibName) { try { return getMibOID(mibName).toString(); } catch (MIBLookupException e) { return null; } } /* * Begins a "session" with an SNMP agent. * @param version The version of SNMP to use. Can be one of the following * values: VERSION_1, VERSION_2C, VERSION_3 * @return A SNMPSession object to be used in all future communications with * the SNMP agent. */ static SNMPSession startSession(int version) throws SNMPException { switch (version) { case VERSION_1: return new SNMPSession_v1(); case VERSION_2C: return new SNMPSession_v2c(); case VERSION_3: return new SNMPSession_v3(); default: throw new SNMPException("Invalid SNMP Version: " + version); } } public boolean init(Properties props) throws SNMPException { // Mainly for debugging... final String prop = "snmp.sessionCacheExpire"; String expire = props.getProperty(prop); if (expire != null) { this.sessionCacheExpire = Integer.parseInt(expire) * 1000; } if (mibTree == null) { mibTree = MIBTree.getInstance(); sessionCache = new IntHashMap(); } return true; } public SNMPSession getSession(ConfigResponse config) throws SNMPException { return getSession(config.toProperties()); } public SNMPSession getSession(Properties props) throws SNMPException { String address = props.getProperty(PROP_IP, DEFAULT_IP); String port = props.getProperty(PROP_PORT, DEFAULT_PORT_STRING); String version = props.getProperty(PROP_VERSION, VALID_VERSIONS[1]); String community = props.getProperty(PROP_COMMUNITY, DEFAULT_COMMUNITY); String transport = props.getProperty(PROP_TRANSPORT, DEFAULT_TRANSPORT); String user = props.getProperty(PROP_USER, DEFAULT_USERNAME); String authtype = props.getProperty(PROP_AUTHTYPE, DEFAULT_AUTHTYPE); String authpass = props.getProperty(PROP_PASSWORD, DEFAULT_PASSWORD); String privtype = props.getProperty(PROP_PRIV_TYPE, DEFAULT_PRIV_TYPE); String privpass = props.getProperty(PROP_PRIV_PASSPHRASE, DEFAULT_PASSWORD); String retries = props.getProperty(PROP_RETRIES, DEFAULT_RETRIES); String timeout = props.getProperty(PROP_TIMEOUT, DEFAULT_TIMEOUT); SNMPSession session = null; int id = address.hashCode() ^ port.hashCode() ^ version.hashCode() ^ community.hashCode() ^ transport.hashCode() ^ user.hashCode() ^ authtype.hashCode() ^ authpass.hashCode() ^ privtype.hashCode() ^ privpass.hashCode() ^ retries.hashCode() ^ timeout.hashCode(); synchronized (sessionCache) { session = (SNMPSession) sessionCache.get(id); } if (session != null) { return session; } int snmpVersion = parseVersion(version); try { session = startSession(snmpVersion); switch (snmpVersion) { case SNMPClient.VERSION_1: case SNMPClient.VERSION_2C: ((SNMPSession_v1) session).init(address, port, community, transport, retries, timeout); break; case SNMPClient.VERSION_3: ((SNMPSession_v3) session).init(address, port, transport, user, authtype, authpass, privtype, privpass, retries, timeout); break; default: throw new SNMPException("Unsupported SNMP version: " + snmpVersion); } } catch (SNMPException e) { String msg = "Failed to initialize SNMP session: " + e.getMessage(); throw new SNMPException(msg, e); } session = SNMPSessionCache.newInstance(session, this.sessionCacheExpire); synchronized (sessionCache) { sessionCache.put(id, session); } return session; } }