/**
* Copyright (C) 2011 Matt Doyle (chief@chiefly.org)
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.chiefly.sunlamp;
import java.io.IOException;
import org.chiefly.sunlamp.util.VariableBindings;
import org.snmp4j.PDU;
import org.snmp4j.Snmp.ReportHandler;
import org.snmp4j.Target;
import org.snmp4j.TransportMapping;
import org.snmp4j.UserTarget;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.event.ResponseListener;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModel;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.Address;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.VariableBinding;
import com.google.common.base.Preconditions;
/**
* {@link SNMPv3} implementation. Example usage:
*
* <pre>
* final OctetString secName = new OctetString("s3cn4m3");
* final OctetString authPass = new OctetString("4uthp4ss");
* final OctetString privPass = new OctetString("pr1vp4ss");
* final UsmUser user = new UsmUser(secName, AuthSHA.ID, authPass, PrivAES128.ID, privPass);
* final TransportMapping<UdpAddress> transport = new DefaultUdpTransportMapping();
* final SnmpClientV3<UdpAddress> v3Client = new StandardSnmpClientV3<UdpAddress>(user, new OctetString(), transport);
* final UdpAddress address = new UdpAddress("192.168.10.10/161");
* final OID oid = new OID("1.2.3.4.5.6");
* final ResponseEvent response = v3Client.getSync(address, oid);
* </pre>
* */
public class StandardSNMPv3<A extends Address> extends AbstractSNMP<A> implements SNMPv3<A> {
/** The {@link UsmUser} to authenticate with. */
private final UsmUser user;
/**
* @param usmUser The {@link UsmUser} to use.
* @param transportMapping The {@link TransportMapping} to use.
* @throws IOException if a {@link TransportMapping} throws an {@link IOException}.
*/
public StandardSNMPv3(final UsmUser usmUser, final TransportMapping<A> transportMapping) throws IOException {
this(usmUser, transportMapping, DEFAULT_RETRIES, DEFAULT_TIMEOUT);
}
/**
* @param usmUser The {@link UsmUser} to use.
* @param transportMapping The {@link TransportMapping} to use.
* @param retries The number of times to retry a request.
* @param timeout The timeout for a given request (in milliseconds).
* @throws IOException if a {@link TransportMapping} throws an {@link IOException}.
*/
public StandardSNMPv3(final UsmUser usmUser, final TransportMapping<A> transportMapping, final int retries,
final long timeout) throws IOException {
this(usmUser, transportMapping, retries, timeout, null);
}
/**
* @param usmUser The {@link UsmUser} to use.
* @param transportMapping The {@link TransportMapping} to use.
* @param retries The number of times to retry a request.
* @param timeout The timeout for a given request (in milliseconds).
* @param reportHandler The (optional) {@link ReportHandler} to use.
* @throws IOException if a {@link TransportMapping} throws an {@link IOException}.
*/
public StandardSNMPv3(final UsmUser usmUser, final TransportMapping<A> transportMapping, final int retries,
final long timeout, final ReportHandler reportHandler) throws IOException {
super(transportMapping, retries, timeout, reportHandler);
this.user = Preconditions.checkNotNull(usmUser);
final USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
this.getSnmp().getUSM().addUser(usmUser);
}
/**
* @see org.chiefly.sunlamp.SNMPv2#getBulkAsync(org.snmp4j.smi.Address, int, int, org.snmp4j.event.ResponseListener,
* java.lang.Object, org.snmp4j.smi.OID[])
*/
@Override
public void getBulkAsync(final A address, final int maxRepetitions, final int nonRepeaters,
final ResponseListener listener, final Object handle, final OID... oids) throws IOException {
checkNoNulls(address, listener, oids);
final Target target = this.createTarget(address);
final PDU requestPdu = this.createRequestPdu(PDU.GETBULK, target, VariableBindings.wrapOids(oids));
requestPdu.setMaxRepetitions(maxRepetitions);
requestPdu.setNonRepeaters(nonRepeaters);
this.getSnmp().send(requestPdu, target, handle, listener);
}
/**
* @see org.chiefly.sunlamp.SNMPv2#getBulkSync(org.snmp4j.smi.Address, int, int, org.snmp4j.smi.OID[])
*/
@Override
public ResponseEvent getBulkSync(final A address, final int maxRepetitions, final int nonRepeaters,
final OID... oids) throws IOException {
checkNoNulls(address, oids);
final Target target = this.createTarget(address);
final PDU requestPdu = this.createRequestPdu(PDU.GETBULK, target, VariableBindings.wrapOids(oids));
requestPdu.setMaxRepetitions(maxRepetitions);
requestPdu.setNonRepeaters(nonRepeaters);
return this.getSnmp().send(requestPdu, target);
}
/**
* @see org.chiefly.sunlamp.SNMPv2#informAsync(org.snmp4j.smi.Address, org.snmp4j.event.ResponseListener,
* java.lang.Object, org.snmp4j.smi.VariableBinding[])
*/
@Override
public void informAsync(final A address, final ResponseListener listener, final Object handle,
final VariableBinding... bindings) throws IOException {
checkNoNulls(address, listener, bindings);
final Target target = this.createTarget(address);
final PDU requestPdu = this.createRequestPdu(PDU.INFORM, target, bindings);
this.getSnmp().send(requestPdu, target, handle, listener);
}
/**
* @see org.chiefly.sunlamp.SNMPv2#informSync(org.snmp4j.smi.Address, org.snmp4j.smi.VariableBinding[])
*/
@Override
public ResponseEvent informSync(final A address, final VariableBinding... bindings) throws IOException {
checkNoNulls(address, bindings);
final Target target = this.createTarget(address);
final PDU requestPdu = this.createRequestPdu(PDU.INFORM, target, bindings);
return this.getSnmp().send(requestPdu, target);
}
/**
* @see org.chiefly.sunlamp.SNMPv2#notify(org.snmp4j.smi.Address, org.snmp4j.smi.VariableBinding[])
*/
@Override
public void notify(final A address, final VariableBinding... bindings) throws IOException {
checkNoNulls(address, bindings);
final Target target = this.createTarget(address);
final PDU requestPdu = this.createRequestPdu(PDU.NOTIFICATION, target, bindings);
this.getSnmp().send(requestPdu, target);
}
/** @see org.chiefly.sunlamp.AbstractSNMP#createVersionSpecificTarget() */
@Override
protected Target createVersionSpecificTarget() {
final UserTarget target = new UserTarget();
target.setVersion(SnmpConstants.version3);
target.setSecurityLevel(this.determineSecurityLevel());
target.setSecurityModel(SecurityModel.SECURITY_MODEL_USM);
target.setSecurityName(this.user.getSecurityName());
return target;
}
/**
* Decides which {@link SecurityLevel} should be used based on the {@link UsmUser}.
*
* @return Returns a {@link SecurityLevel} value.
*/
private int determineSecurityLevel() {
final boolean auth = ((this.user.getAuthenticationProtocol() != null) && (this.user
.getAuthenticationPassphrase() != null));
final boolean priv = ((this.user.getPrivacyProtocol() != null) && (this.user.getPrivacyPassphrase() != null));
/* Highest security by default */
int securityLevel = SecurityLevel.AUTH_PRIV;
/* Decide on a security level */
if (!auth && !priv) {
securityLevel = SecurityLevel.NOAUTH_NOPRIV;
} else if (auth && !priv) {
securityLevel = SecurityLevel.AUTH_NOPRIV;
}
return securityLevel;
}
}