Length of original trap in incoming buffer and TransportListener interface

Hi,

We would like to change SNMP4J version from 2.5.3 to 3.3.1, but we encountered following problem in trap receiving area. We use trap processing in 2 ways:

  • full processing done by SNMP4J (using following interface: org.snmp4j.CommandResponder#processPdu)
  • forwarding original trap to external system (using following interface: org.snmp4j.transport.TransportListener#processMessage)
    We have a problem in second use case - in our scenario we take original message (provided via org.snmp4j.transport.TransportListener#processMessage) and forward it using Datagram to defined address. And we got following errors:
  • java.net.SocketException: The message is larger than the maximum supported by the underlying transport: Datagram send failed
  • or java.io.IOException: Message too long
    The reason of that is that in version 3.3.1 you invoke “processMessage” always with full length buffer (org.snmp4j.transport.AbstractTransportMapping#maxInboundMessageSize -> 65535) containing the original version of message (doesn’t matter what is the length of this message). In our case this buffer is too big to send it again as datagram message because max value for data in UDP is 65,507 bytes.
    In 2.5.3 you provided buffer with original message length.
    Questions:
  • is it possible to add original message length in org.snmp4j.transport.TransportListener#processMessage?
  • is there any other way to get original message length?
  • is there any other way to take original trap?

I know that we can send message with the max value of 65507 bytes but I think it is not a good approach when typical UDP messages are much smaller.
Looking forward for any hints. Thank you.

Best regards
Tomek

Hi Tomek,

Which setting of isAsyncMsgProcessingSupported() of your TransportMapping are you using. If set to true, the provided buffer will be exactly the size of the read data. However, it is never guaranteed that the read data length matches the SNMOP message length.

Best regards,
Frank

Hi Frank,

Some info from debug of DefaultUdpTransportMapping class (v3.3.1, listen thread):
isAsyncMsgProcessingSupported() = true

What I see in 3.3.1 source code, for this case new buffer is created before each socket receive:

if (isAsyncMsgProcessingSupported() || (buf == null)) {
buf = new byte[getMaxInboundMessageSize()];
}
where
getMaxInboundMessageSize()=65535

Later HeapByteBuffer is created:

bis = prepareInPacket(packet, buf, stateReference);

Internal byte array in this buffer has max value -> 65535, even when message received by socket is smaller (in my example it is 255).
In previous releases in this place this buffer was cut for Async option (it is in our current version 2.5.3) but now it is not (3.3.1).
This buffer is later forwarded via processMessage to registered listeners (with 65535 length).

Tomek

Hi Tomek,

OK, I found the issue (it was unclear to me that you use UDP, with TCP the issue is no there). You can workaround it by subclassing DefaultUdpTransportMapping and overwriting the following method: (as show below)

protected ByteBuffer prepareInPacket(DatagramPacket packet, byte[] buf, TransportStateReference tmStateReference)
        throws IOException {
    return ByteBuffer.wrap(packet.getData(), 0, packet.getLength());
}

This fix will be part of he next release though.

Best regards,
Frank

Great, it is OK for me. Thanks for your support.
Best regards
Tomek