/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2010-2011 The OpenNMS Group, Inc.
* OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
*
* OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
*
* OpenNMS(R) is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* OpenNMS(R) 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 OpenNMS(R). If not, see:
* http://www.gnu.org/licenses/
*
* For more information contact:
* OpenNMS(R) Licensing <license@opennms.org>
* http://www.opennms.org/
* http://www.opennms.com/
*******************************************************************************/
package org.opennms.mock.snmp;
import static org.junit.Assert.*;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.ScopedPDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.UserTarget;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.MPv3;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.security.AuthMD5;
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.Counter32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.SMIConstants;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.Variable;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;
@RunWith(Parameterized.class)
public class BrocadeMibTest {
@Parameters
public static Collection<Object[]> versions() {
return Arrays.asList(new Object[][] {
{ SnmpConstants.version1 },
{ SnmpConstants.version2c },
{ SnmpConstants.version3 },
});
}
private MockSnmpAgent m_agent;
private USM m_usm;
private ArrayList<AnticipatedRequest> m_requestedVarbinds;
private int m_version;
public BrocadeMibTest(int version) {
m_version = version;
}
private class AnticipatedRequest {
private String m_requestedOid;
private Variable m_requestedValue;
private String m_expectedOid;
private int m_expectedSyntax;
private Variable m_expectedValue;
public AnticipatedRequest(String requestedOid, Variable requestedValue) {
m_requestedOid = requestedOid;
m_requestedValue = requestedValue;
}
public void andExpect(String expectedOid, int expectedSyntax, Variable expectedValue) {
m_expectedOid = expectedOid;
m_expectedSyntax = expectedSyntax;
m_expectedValue = expectedValue;
}
public VariableBinding getRequestVarbind() {
OID oid = new OID(m_requestedOid);
if (m_requestedValue != null) {
return new VariableBinding(oid, m_requestedValue);
} else {
return new VariableBinding(oid);
}
}
public void verify(VariableBinding vb) {
assertNotNull("variable binding should not be null", vb);
Variable val = vb.getVariable();
assertNotNull("variable should not be null", val);
assertEquals("OID (value: " + val + ")", new OID(m_expectedOid), vb.getOid());
assertEquals("syntax", m_expectedSyntax, vb.getSyntax());
assertEquals("value", m_expectedValue, val);
}
}
@Before
public void setUp() throws Exception {
// Create a global USM that all client calls will use
MPv3.setEnterpriseID(5813);
m_usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(m_usm);
m_agent = MockSnmpAgent.createAgentAndRun(classPathResource("brocadeTestData1.properties"), "127.0.0.1/1691"); // Homage to Empire
m_requestedVarbinds = new ArrayList<AnticipatedRequest>();
}
@After
public void tearDown() throws Exception {
if (m_agent != null) {
m_agent.shutDownAndWait();
}
}
public AnticipatedRequest request(String requestedOid, Variable requestedValue) {
AnticipatedRequest r = new AnticipatedRequest(requestedOid, requestedValue);
m_requestedVarbinds.add(r);
return r;
}
public AnticipatedRequest request(String requestOid) {
return request(requestOid, null);
}
public void reset() {
m_requestedVarbinds.clear();
}
/**
* Make sure that we can setUp() and tearDown() the agent.
* @throws InterruptedException
*/
@Test
public void testAgentSetup() {
assertNotNull("agent should be non-null", m_agent);
}
/**
* Test that we can setUp() and tearDown() twice to ensure that the
* MockSnmpAgent tears itself down properly. In particular, we want to make
* sure that the UDP listener gets torn down so listening port is free for
* later instances of the agent.
*
* @throws Exception
*/
@Test
public void testSetUpTearDownTwice() throws Exception {
// don't need the first setUp(), since it's already been done by JUnit
tearDown();
setUp();
// don't need the second tearDown(), since it will be done by JUnit
}
@Test
public void testGetNext() throws Exception {
request(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11").andExpect(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11.1", SMIConstants.SYNTAX_COUNTER32, new Counter32(128350705));
doGetNext();
request(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11.1").andExpect(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11.2", SMIConstants.SYNTAX_COUNTER32, new Counter32(1047537430));
doGetNext();
}
@Test
public void testGetNextMultipleVarbinds() throws Exception {
request(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11").andExpect(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11.1", SMIConstants.SYNTAX_COUNTER32, new Counter32(128350705));
doGetNext();
m_agent.getUsm().setEngineBoots(15);
byte[] hexString = new byte[] { (byte)0x11, (byte)0x00, (byte)0x33, (byte)0x44, (byte)0x55, (byte)0x66, (byte)0x77, (byte)0x88 };
request(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11").andExpect(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11.1", SMIConstants.SYNTAX_COUNTER32, new Counter32(128350705));
request(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.12").andExpect(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.12.1", SMIConstants.SYNTAX_COUNTER32, new Counter32(3180401803L));
request(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.34").andExpect(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.34.1", SMIConstants.SYNTAX_OCTET_STRING, new OctetString(hexString));
doGetNext();
// This statement breaks the internal state of the SNMP4J agent
// m_agent.getUsm().setLocalEngine(m_agent.getUsm().getLocalEngineID(), 15, 200);
m_agent.getUsm().removeEngineTime(m_usm.getLocalEngineID());
m_usm.removeEngineTime(m_agent.getUsm().getLocalEngineID());
request(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11.1").andExpect(".1.3.6.1.4.1.1588.2.1.1.1.6.2.1.11.2", SMIConstants.SYNTAX_COUNTER32, new Counter32(1047537430));
doGetNext();
}
private void doGetNext() throws Exception {
requestAndVerifyResponse(PDU.GETNEXT, m_version);
}
private void requestAndVerifyResponse(int pduType, int version) throws Exception {
PDU pdu = createPDU(version);
for(AnticipatedRequest a : m_requestedVarbinds) {
pdu.add(a.getRequestVarbind());
}
pdu.setType(pduType);
PDU response = sendRequest(pdu, version);
assertNotNull("request timed out", response);
System.err.println("Response is: "+response);
assertTrue("unexpected report pdu: " + ((VariableBinding)response.getVariableBindings().get(0)).getOid(), response.getType() != PDU.REPORT);
assertEquals("Unexpected number of varbinds returned.", m_requestedVarbinds.size(), response.getVariableBindings().size());
for(int i = 0; i < m_requestedVarbinds.size(); i++) {
AnticipatedRequest a = m_requestedVarbinds.get(i);
VariableBinding vb = response.get(i);
a.verify(vb);
}
reset();
}
private PDU createPDU(int version) {
if (version == SnmpConstants.version3) {
return new ScopedPDU();
} else {
return new PDU();
}
}
private PDU sendRequest(PDU pdu, int version) throws Exception {
if (version == SnmpConstants.version3) {
return sendRequestV3(pdu);
} else {
return sendRequestV1V2(pdu, version);
}
}
private PDU sendRequestV1V2(PDU pdu, int version) throws Exception {
PDU response;
CommunityTarget target = new CommunityTarget();
target.setCommunity(new OctetString("public"));
target.setAddress(new UdpAddress(InetAddress.getByName("127.0.0.1"), 1691));
target.setVersion(version);
TransportMapping transport = null;
try {
transport = new DefaultUdpTransportMapping();
Snmp snmp = new Snmp(transport);
transport.listen();
ResponseEvent e = snmp.send(pdu, target);
response = e.getResponse();
} finally {
if (transport != null) {
transport.close();
}
}
return response;
}
private PDU sendRequestV3(PDU pdu) throws IOException {
PDU response;
OctetString userId = new OctetString("opennmsUser");
OctetString pw = new OctetString("0p3nNMSv3");
UserTarget target = new UserTarget();
target.setSecurityLevel(SecurityLevel.AUTH_PRIV);
target.setSecurityName(userId);
target.setAddress(new UdpAddress(InetAddress.getByName("127.0.0.1"), 1691));
target.setVersion(SnmpConstants.version3);
target.setTimeout(5000);
TransportMapping transport = null;
try {
USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
SecurityModels.getInstance().addSecurityModel(usm);
transport = new DefaultUdpTransportMapping();
Snmp snmp = new Snmp(transport);
UsmUser user = new UsmUser(userId, AuthMD5.ID, pw, PrivDES.ID, pw);
snmp.getUSM().addUser(userId, user);
transport.listen();
ResponseEvent e = snmp.send(pdu, target);
response = e.getResponse();
} finally {
if (transport != null) {
transport.close();
}
}
return response;
}
private URL classPathResource(String path) {
return getClass().getClassLoader().getResource(path);
}
}