SNMP4j - 无法在某些OID上发送RESPONSE PDU

时间:2014-12-30 16:33:07

标签: response snmp snmp4j

我尝试使用SNMP4j 2.3.1(在Windows上运行)响应来自SnmpB的SNMP GET请求。

In"发现"模式,SnmpB查询通过广播255.255.255.255(使用Wireshark检查),我收到标准OID(sysDescr,sysUpTime,sysContact,sysName和sysLocation)的GET请求。它使用我编码的信息找到我的实例("我的系统","我自己",...)(请注意,当我输入&#34下的IP地址时,它也有效; IP网络"文本框,虽然我在Wireshark上看不到任何流量,但我收到了GET请求):

SnmpB discovery

我写了一个非常简单的MIB文件,我导入了SnmpB。它定义了我想要使用来自SnmpB的SNMP GET请求检索的单个Integer32数据。

但是,使用相同代码而不是标准sys * OID,SnmpB似乎无法接收该数据(" Timeout"顶部为红色 - 右):

SnmpB timeout

我确实尝试过Wireshark检查网络活动而我看不到任何内容,所以我猜它会发生在localhost(not accessible with Wireshark on Windows)上?但是下面的痕迹显示它没有(peerAddress=192.168.56.1)......

这是MIB文件(代码如下):

MY-TEST-MIB DEFINITIONS ::= BEGIN

IMPORTS
    enterprises, MODULE-IDENTITY, OBJECT-TYPE, Integer32
        FROM SNMPv2-SMI;

myTest MODULE-IDENTITY
    LAST-UPDATED "201412301216Z"
    ORGANIZATION "My org"
    CONTACT-INFO "Matthieu Labas"
    DESCRIPTION "MIB Test"
    REVISION "201412301216Z"
    DESCRIPTION "Generated"
    ::= { enterprises 12121 }

myData OBJECT-TYPE
    SYNTAX Integer32
    MAX-ACCESS read-only
    STATUS current
    DESCRIPTION "My data for test"
    ::= { myTest 1 }

END

...和代码:

public class RespondGET implements CommandResponder {

    public static final OID sysDescr = new OID("1.3.6.1.2.1.1.1.0");
    public static final OID sysUpTime = new OID("1.3.6.1.2.1.1.3.0");
    public static final OID sysContact = new OID("1.3.6.1.2.1.1.4.0");
    public static final OID sysName = new OID("1.3.6.1.2.1.1.5.0");
    public static final OID sysLocation = new OID("1.3.6.1.2.1.1.6.0");

    public static final OID myData = new OID("1.3.6.1.4.1.12121.1.0");

    private Snmp snmp;

    public RespondGET() throws IOException {
        MessageDispatcher dispatcher = new MessageDispatcherImpl();
        dispatcher.addMessageProcessingModel(new MPv2c()); // v2c only
        snmp = new Snmp(dispatcher, new DefaultUdpTransportMapping(new UdpAddress("192.168.56.1/161"), true));
        snmp.addCommandResponder(this);
        snmp.listen();
    }

    @Override
    public void processPdu(CommandResponderEvent event) {
        System.out.println("Received PDU "+event);
        PDU pdu = event.getPDU();
        switch (pdu.getType()) {
            case PDU.GET:
                List<VariableBinding> responses = new ArrayList<VariableBinding>(pdu.size());
                for (VariableBinding v : pdu.getVariableBindings()) {
                    OID oid = v.getOid();
                    // Answer the usual SNMP requests
                    if (sysDescr.equals(oid)) {
                        responses.add(new VariableBinding(oid, new OctetString("My System description")));
                    } else if (sysUpTime.equals(oid)) {
                        responses.add(new VariableBinding(oid, new TimeTicks(ManagementFactory.getRuntimeMXBean().getUptime())));
                    } else if (sysContact.equals(oid)) {
                        responses.add(new VariableBinding(oid, new OctetString("Myself")));
                    } else if (sysName.equals(oid)) {
                        responses.add(new VariableBinding(oid, new OctetString("My System")));
                    } else if (sysLocation.equals(oid)) {
                        responses.add(new VariableBinding(oid, new OctetString("In here")));
                    } else if (myData.equals(oid)) { // MyData handled here
                        responses.add(new VariableBinding(oid, new Integer32(18)));
                    }
                }

                try {
                    CommunityTarget comm = new CommunityTarget(event.getPeerAddress(), new OctetString(event.getSecurityName()));
                    comm.setSecurityLevel(event.getSecurityLevel());
                    comm.setSecurityModel(event.getSecurityModel());
                    PDU resp = new PDU(PDU.RESPONSE, responses);
                    System.out.println(String.format("Sending response PDU to %s/%s: %s", event.getPeerAddress(), new String(event.getSecurityName()), resp));
                    snmp.send(resp, comm);
                } catch (IOException e) {
                    System.err.println(String.format("Unable to send response PDU! (%s)", e.getMessage()));
                }
                event.setProcessed(true);
                break;

            default:
                System.err.println(String.format("Unhandled PDU type %s.", PDU.getTypeString(pdu.getType())));
                break;
        }
    }

    public static void main(String[] args) throws IOException {
        RespondGET rg = new RespondGET();
        System.out.println("Listening...");
        int n = 300; // 5 min
        while (true) {
            try { Thread.sleep(1000); } catch (InterruptedException e) { }
            if (--n <= 0) break;
        }
        System.out.println("Stopping...");
        rg.snmp.close();
    }

}

当我点击&#34;发现&#34>时,它产生以下输出;在SnmpB下,右键单击MIB树中的myData和&#34;获取&#34; (为了便于阅读,略微重新格式化):

Listening...
Received PDU CommandResponderEvent[securityModel=2, securityLevel=1, maxSizeResponsePDU=65535,
    pduHandle=PduHandle[16736], stateReference=StateReference[msgID=0,pduHandle=PduHandle[16736],
    securityEngineID=null,securityModel=null,securityName=public,securityLevel=1,
    contextEngineID=null,contextName=null,retryMsgIDs=null], pdu=GET[requestID=16736, errorStatus=Success(0), errorIndex=0,
    VBS[1.3.6.1.2.1.1.1.0 = Null; 1.3.6.1.2.1.1.3.0 = Null; 1.3.6.1.2.1.1.4.0 = Null; 1.3.6.1.2.1.1.5.0 = Null; 1.3.6.1.2.1.1.6.0 = Null]],
    messageProcessingModel=1, securityName=public, processed=false, peerAddress=192.168.56.1/49561, transportMapping=org.snmp4j.transport.DefaultUdpTransportMapping@120d62b, tmStateReference=null]

Sending response PDU to 192.168.56.1/49561/public: RESPONSE[requestID=0, errorStatus=Success(0), errorIndex=0,
    VBS[1.3.6.1.2.1.1.1.0 = My System description; 1.3.6.1.2.1.1.3.0 = 0:01:03.18; 1.3.6.1.2.1.1.4.0 = Myself; 1.3.6.1.2.1.1.5.0 = My System; 1.3.6.1.2.1.1.6.0 = In here]]

Received PDU CommandResponderEvent[securityModel=2, securityLevel=1, maxSizeResponsePDU=65535,
    pduHandle=PduHandle[1047], stateReference=StateReference[msgID=0,pduHandle=PduHandle[1047],
    securityEngineID=null,securityModel=null,securityName=public,securityLevel=1,
    contextEngineID=null,contextName=null,retryMsgIDs=null], pdu=GET[requestID=1047, errorStatus=Success(0), errorIndex=0,
    VBS[1.3.6.1.4.1.12121.1.0 = Null]], messageProcessingModel=1, securityName=public, processed=false, peerAddress=192.168.56.1/49560, transportMapping=org.snmp4j.transport.DefaultUdpTransportMapping@120d62b, tmStateReference=null]

Sending response PDU to 192.168.56.1/49560/public: RESPONSE[requestID=0, errorStatus=Success(0), errorIndex=0, VBS[1.3.6.1.4.1.12121.1.0 = 18]]

Stopping...

我在这里缺少什么?那可能&#34;只是&#34;是一个网络路由问题?

1 个答案:

答案 0 :(得分:1)

在设置VM并使用Wireshark检查后,结果发现我忘了在响应PDU上设置与GET PDU相同的请求ID。

GET request ID Response null request ID

通过在构建响应PDU时添加resp.setRequestID(pdu.getRequestID());来解决它

CommunityTarget comm = new CommunityTarget(event.getPeerAddress(), new OctetString(event.getSecurityName()));
comm.setSecurityLevel(event.getSecurityLevel());
comm.setSecurityModel(event.getSecurityModel());
PDU resp = new PDU(PDU.RESPONSE, responses);
resp.setRequestID(pdu.getRequestID()); // Forgot that!
snmp.send(resp, comm);

SnmpB received PDU

感谢@Jolta在新年假期期间的耐心以及他坚持使用Wireshark进行进一步检查。 :)