[SNMP4J] random problem sending command over TCP

Brice Fines bfines at sermepa.es
Thu Nov 5 11:32:37 CET 2009


Hi Frank,

No, it seems we are not using 
TransportStateListener.connectionStateChanged (I could not find any 
reference to TransportStateListener in the whole code).

We use SNMP4J in a straight forward way: configure and init an SNMP object 
for the whole application life, use it to send commands.

Please find enclosed the source for the class we use (to send a command we 
call the "sendCommand" method, that's where the application hangs (but 
only a few times, it works ok 99% of the time)
(I still have to check with version 1.10.2, hope to be able to do it soon)

Thanks

import java.io.IOException;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.ScopedPDU;
import org.snmp4j.Snmp;
import org.snmp4j.Target;
import org.snmp4j.TransportMapping;
import org.snmp4j.UserTarget;
import org.snmp4j.event.CounterListener;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.CounterSupport;
import org.snmp4j.mp.DefaultCounterListener;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.AuthMD5;
import org.snmp4j.security.AuthSHA;
import org.snmp4j.security.PrivDES;
import org.snmp4j.security.SecurityLevel;
import org.snmp4j.security.SecurityModels;
import org.snmp4j.security.SecurityProtocols;
import org.snmp4j.security.USM;
import org.snmp4j.security.UsmUser;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.TcpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultTcpTransportMapping;

import aaa.bbbbbb.xxxxx.business.channel.ControlChannel;
import aaa.bbbbbb.xxxxx.business.dialog.ComandosResolver;
import aaa.bbbbbb.xxxxx.commands.Comando;
import aaa.bbbbbb.xxxxx.exceptions.AccesoDenegadoException;
import aaa.bbbbbb.xxxxx.exceptions.ClientUnreachableException;
import aaa.bbbbbb.xxxxx.exceptions.CommandNotFoundException;
import aaa.bbbbbb.xxxxx.exceptions.InternalErrorException;
import aaa.bbbbbb.xxxxx.exceptions.RespuestaErrorGenerico;
import aaa.bbbbbb.xxxxx.exceptions.RespuestaInvalidaException;
import aaa.bbbbbb.xxxxx.exceptions.SintaxisIncorrectaException;
import aaa.bbbbbb.xxxxx.model.Client;
import aaa.bbbbbb.xxxxx.util.log4j.SourcesLogger;

public class SnmpChannel implements ControlChannel {

        private SourcesLogger logger = new SourcesLogger(getClass());

        private String commandPort = "/161";

        public void setCommandPort(String commandPort) {
                this.commandPort = commandPort;
        }

        private int timeout = 10 * 1000;

        public void setTimeout(int timeout) {
                this.timeout = timeout * 1000;
        }

        private int retries = 3;

        public void setRetries(int retries) {
                this.retries = retries;
        }

        private String community = "ppp";

        public void setCommunity(String community) {
                this.community = community;
        }

        private boolean soportaVersion3 = false;

        public void setV3(boolean soportaVersion3) {
                this.soportaVersion3 = soportaVersion3;
        }
        private String securityName = "";

        public void setSecurityName(String securityName) {
                this.securityName = securityName;
        }

        private String authProtocol = "";

        public void setAuthProtocol(String authProtocol) {
                this.authProtocol = authProtocol;
        }

        private String authPassphrase = "";

        public void setAuthPassphrase(String authPassphrase) {
                this.authPassphrase = authPassphrase;
        }

        private String privProtocol = "";

        public void setPrivProtocol(String privProtocol) {
                this.privProtocol = privProtocol;
        }

        private String privPassphrase = "";

        public void setPrivPassphrase(String privPassphrase) {
                this.privPassphrase = privPassphrase;
        }

        private Control2SNMP snmpConversionService;

        public void setControl2SNMP(Control2SNMP snmpConversionService) {
                this.snmpConversionService = snmpConversionService;
        }
 
        private ComandosResolver theComandosResolver;
 
        public void setComandosResolver(ComandosResolver 
comandosResolver){
                theComandosResolver = comandosResolver; 
        }

        private Snmp snmp;

        private final CounterListener counterListener = new 
DefaultCounterListener();
 
        private TransportMapping transportMapping;

        public boolean startup() {
                try {
                        logger.getLogger().warn(
                                        logger.fromServer("Starting 
SNMP"));
 CounterSupport.getInstance().addCounterListener(counterListener);
                        snmp = createSnmpSession();
                        snmp.listen();
                        logger
                                        .getLogger()
                                        .warn(
                                                        logger
 .fromServer("SNMP started"));
                        return true;
                } catch (Exception exception) {
 logger.getLogger().error(logger.fromServer(exception.toString()));
                        exception.printStackTrace();
                        return false;
                }
        }

        public void shutdown() {
                try {
                        logger.getLogger().warn(
                                        logger.fromServer("closing 
SNMP"));
 CounterSupport.getInstance().removeCounterListener(counterListener);
                        snmp.close();
                } catch (Exception exception) {
 logger.getLogger().warn(logger.fromServer(exception.toString()));
                        exception.printStackTrace();
                }
        }

        public Comando sendCommand(Client client, Comando comando)
                        throws   ClientUnreachableException, 
AccesoDenegadoException,
                        SintaxisIncorrectaException, 
RespuestaInvalidaException, CommandNotFoundException,
                        RespuestaErrorGenerico, InternalErrorException
 
                {
                final ResponseEvent responseEvent ;
                try {
                        final PDU pdu = comando2PDU(comando);
 
                        if(pdu == null){
                                throw new InternalErrorException("PDU not 
found");
                        }
                        final String ip = client.getIp();
                        final Target target = createTarget(ip);
                         responseEvent = snmp.send(pdu, target);
                } catch (Exception e) {
                        throw new InternalErrorException("Exception with 
command: " + e + " " + e.getMessage());
                }
 
                if (responseEvent == null) { 
                        throw new ClientUnreachableException("Answer 
null");
                }

                if (responseEvent.getResponse() == null) { 
                        throw new ClientUnreachableException("Answer 
null");
                }
                final PDU pduResponse = responseEvent.getResponse(); 
                if(pduResponse.getType() != PDU.REPORT 
                        && pduResponse.getType() != PDU.RESPONSE){
                        throw new RespuestaInvalidaException("Unknown 
answer: pduResponse.getType()= " + 

pduResponse.getType());
                }
                if (pduResponse.getType() == PDU.REPORT) {
                        throw new AccesoDenegadoException("SNMP REPORT: " 
+ pduResponse.toString());
                }
                if (pduResponse.getErrorStatus() != PDU.noError) {
                        if (pduResponse.getErrorStatus() == 
PDU.authorizationError) {
                                throw new AccesoDenegadoException("SNMP 
answer: autorizationError status");
                        }
                        if(pduResponse.getErrorStatus() == PDU.badValue){ 
                                throw new 
SintaxisIncorrectaException("SNMP answer: badValue status");
                        }
                        if(pduResponse.getErrorStatus() == PDU.noSuchName
                                || pduResponse.getErrorStatus() == 
PDU.readOnly){
                                throw new CommandNotFoundException("SNMP 
answer: noSuchName/readOnly status");
                        }
 
                        boolean posibleMsgError = 
pduResponse.getErrorStatus() == PDU.genErr && !comando.isGet()? true : 

false;
                        throw new RespuestaErrorGenerico(posibleMsgError, 
"SNMP answer: " + 

pduResponse.getErrorStatusText());
                }
                if (pduResponse.getVariableBindings().size() == 0) {
                        throw new RespuestaInvalidaException("SNMP answer 
with no varBind");
                }
                try{
                        final VariableBinding variableBinding = 
pduResponse.get(0);
                        String res = 
snmpConversionService.getStringValue(variableBinding);
                        comando.setResultado(res);
                        return comando;
 
                }catch(Exception e){
                        throw new RespuestaInvalidaException("Exception 
parsing answer: "+ e + " " +e.getMessage());
                }
 
        }

        private Snmp createSnmpSession() throws IOException {
                logger.getLogger().debug(logger.fromServer("Creating SNMP 
session"));
                transportMapping = new DefaultTcpTransportMapping();
                final Snmp snmp = new Snmp(transportMapping);
                if (soportaVersion3) {
                        final USM usm = new 
USM(SecurityProtocols.getInstance(),
                                        new 
OctetString(MPv3.createLocalEngineID()), 0);
 SecurityModels.getInstance().addSecurityModel(usm);
                        addUsmUser(snmp);
                        logger.getLogger().debug(
                                        logger.fromServer("SNMP session 
created"));
                }
                return snmp;
        }

        private void addUsmUser(Snmp snmp) {
                logger.getLogger().debug(
                                logger.fromServer("Creating SNMP user " + 
securityName
                                                + ", Protocolo " + 
authProtocol));
                snmp.getUSM().addUser(
                                new OctetString(securityName),
                                new UsmUser(new OctetString(securityName), 
authProtocol
                                                .equals("MD5") ? 
AuthMD5.ID : AuthSHA.ID,
                                                authPassphrase.length() != 
0 ? new OctetString(
 authPassphrase) : null,
                                                privProtocol.length() != 0 
? PrivDES.ID : null,
                                                privPassphrase.length() != 
0 ? new OctetString(
 privPassphrase) : null));
        }

        private Target createTarget(String ip) {
                Target target = null;
                if (soportaVersion3) {
                        target = createSecuredUserTarget(ip);
                } else {
                        target = createCommunityTarget(ip);
                }
                target.setTimeout(timeout);
                target.setRetries(retries);
                return target;
        }

        private Target createSecuredUserTarget(String ip) {
                final UserTarget userTarget = new UserTarget();
                if (authPassphrase != null && authPassphrase.length() != 
0) {
                        if (privPassphrase != null && 
privPassphrase.length() != 0) {
 userTarget.setSecurityLevel(SecurityLevel.AUTH_PRIV);
                        } else {
 userTarget.setSecurityLevel(SecurityLevel.AUTH_NOPRIV);
                        }
                } else {
 userTarget.setSecurityLevel(SecurityLevel.NOAUTH_NOPRIV);
                }
                userTarget.setSecurityName(new OctetString(securityName));
                userTarget.setVersion(SnmpConstants.version3);
                userTarget.setAddress(new TcpAddress(ip + commandPort));
                return userTarget;
        }

        private Target createCommunityTarget(String ip) {
                final CommunityTarget communityTarget = new 
CommunityTarget();
                communityTarget.setCommunity(new OctetString(community));
                communityTarget.setAddress(new TcpAddress(ip + 
commandPort));
                return communityTarget;
        }

        private PDU comando2PDU(Comando cmd) {
                final PDU pdu = soportaVersion3 ? new ScopedPDU() : new 
PDU();
                pdu.setType(cmd.isGet() ? PDU.GET : PDU.SET);
                final String mibId = 
theComandosResolver.getMibIdFromDBCodigo(cmd.getCodigoComando());
                if(mibId == null){
                        return null;
                }
                final OID oid = snmpConversionService.findOID(mibId);
                if(oid == null){
                        return null;
                }
 
                final VariableBinding variableBinding = new 
VariableBinding(oid);
                if (cmd.isGet() == false) {
                        variableBinding.setVariable(snmpConversionService
 .createSNMPVariable(cmd.getParam()));
                }
                pdu.add(variableBinding);
                return pdu;
        }

}


More information about the SNMP4J mailing list