Search code examples
windowssnmpwinsnmp

How should I test if a PDU is too big in WinSNMP?


I am building an SNMP Agent for a Windows application using the Microsoft WinSNMP API. Currently everything is working for single-item get and set-request, and also for get-next to allow walking the defined tree (albeit with some caveats that are not relevant to this question).

I am now looking at multi-item get and also get-bulk.

My current procedure is to iterate through the list of requested items (the varbindlist within the PDU), treating each one individually, effectively causing an internal get. The result is added to the VBL, set into the PDU, and then sent back to the SNMP Manager, taking into account invalid requests, etc.

My question is how should I handle "too much" data (data that cannot fit into a single transport layer message)? Or more accurately, is there a way to test whether data is "too big" without actually attempting to transmit? The only way I can see in the API is to try sending, check the error, and try again.

In the case of a get-request this isn't a problem - if you can't return all of the requested data, you fail: so attempt sending, and if the error report is SNMPAPI_TL_PDU_TOO_BIG, send a default "error" PDU.

However, it is allowable for a response to bulk-get to return partial results.

The only way I can see to handle this is a tedious (?) loop of removing an item and trying again. Something similar to the following (some detail removed for brevity):

// Create an empty varbindlist
vbl = SnmpCreateVbl(session, NULL, NULL);
// Add all items to the list
SnmpSetVb(vbl, &oid, &value); // for each OID/Value pair
// Create the PDU
pdu = SnmpCreatePdu(session, SNMP_PDU_RESPONSE, ..., vbl);
bool retry;
do {
    retry = false;
    smiINT failed = SnmpSendMsg(session, ..., pdu);
    if (failed && SNMPAPI_TL_PDU_TOO_BIG == SnmpGetLastError()) {
        // too much data, delete the last vb
        SnmpDeleteVb(vbl, SnmpCountVbl(vbl));
        SnmpSetPduData(pdu, ..., vbl);
        retry = true;
    };
} while(retry);

This doesn't seem like an optimal approach - so is there another way that I've missed?


As a side-note, I know about libraries such as net-snmp, but my question is specific to the Microsoft API.


Solution

  • The RFC does require you to do what you pasted,

    https://www.rfc-editor.org/rfc/rfc3416

    Read page 16.

    There does not seem to be a function exposed by WinSNMP API that can do this for you, so you have to write your own logic to handle it.