当前位置: 首页 > 知识库问答 >
问题:

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

司马祖鹤
2023-03-14

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

在“发现”模式下,SnmpB通过广播255.255.255.255(通过Wireshark检查)进行查询,我收到一个带有标准OID(sysDescr、sysUpTime、sysContact、sysName和sysLocation)的GET请求。它使用我编码的信息(“我的系统”、“我自己”等)查找我的实例(请注意,当我在“IP网络”文本框下输入IP地址时,它也可以工作,尽管我在Wireshark上没有看到任何流量,但我收到了GET请求):

我确实编写了一个非常简单的MIB文件,并将其导入了SnmpB。它定义了一个我想使用来自SnmpB的SNMP GET请求检索的单个Intger32数据。

然而,使用与标准sys*OID相同的代码,SnmpB似乎没有收到该数据(“右上角红色的超时”):

我确实尝试过Wireshark检查网络活动,但我什么也没看到,所以我猜它发生在本地主机上(Windows上的Wireshark无法访问)?但下面的痕迹表明它没有(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();
    }

}

当我单击SnmpB下的“discover”并右键单击MIB树中的myData和“Get”(稍微重新格式化以便于可读)时,它会生成以下输出:

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...

我错过了什么?那“只是”是网络路由问题吗?

共有1个答案

梁和颂
2023-03-14

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

通过添加resp解决了这个问题。setRequestID(pdu.getRequestID()) 构建响应PDU时

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);

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

 类似资料:
  • 我正在使用Spring Boot来消费API。对于某些API,它可以工作,但对于另一些API,它失败,返回500个内部服务器错误。例如,当使用此API https://quoters.apps.pcfone.io/API/random时,它工作,但是https://reqres.in/API/unknown/23返回500错误。这是什么原因? 我的代码很简单:

  • 我一直在努力推动我在github上的工作,但我遇到了以下错误:

  • 因此,我试图从linux获取电池状态,到目前为止,第一个命令(path变量)返回得很好,我能够从输入流中以序列的形式获得它的响应,但不幸的是,第二个命令(result变量)返回空序列。 输出: 上面的输出来自最后一个命令中的块,只是为了预览命令的字符串以便调试。如果我直接在终端中运行上面的命令,我将成功地得到如下响应: 为什么最后一个命令不工作(不返回任何响应)与ProcessBuilder? 注

  • 这是我的存储库https://github.com/kiotie32/artbit-text.git 当我这样做的时候 我使用的是Windows 10计算机。我已将ssh密钥配置为与此笔记本电脑一起使用。我做了一个ls,我能看见 我阅读了此线程中给出的所有答案,并更改了存储在windows凭据管理器中的密码。 我检查我得到以下输出 我更改了存储在windows凭据管理器中的密码可能存储了旧密码。

  • 问题内容: 我试图通过ajax jQuery的方法从跨域服务器检索XML,并且控制台上出现以下错误消息: 导致此错误的代码是: 问题答案: 问题是同步选项由以下方式指定: 这似乎在Chrome中不起作用,可能是由于jQuery的ajax方法的规范,该规范说: 跨域请求和dataType:“ jsonp”请求不支持同步操作。 奇怪的是,Firefox和Internet Explorer似乎忽略了该规

  • 我可以在POST请求时发送对象列表作为响应,并在VueJs客户端中接收它 但是当我尝试用自定义类响应时(我甚至在请求映射注释中添加了) 在axios的帮助下发送VueJs端请求。邮递 Vue用户界面客户端接收 为什么我可以用对象列表响应而不能用POJO响应,以及如何解决这个问题?非常感谢。 PS.项目依赖于jackson-数据库v2.8.2和Spring v4.3.1