OidCollections Filter

Hi Frank,

I am trying to better understand how to create a better trap receiver. If I understand correctly appending oids to an Snmp_pp::OidCollection and passing it to the snmp.notify_register function will filter incoming trap notification messages. However I am having a hard time understanding how to implement this.

If I understand correctly passing it an OidCollection object that is empty will just allow any and all notifications through. The following code exhibits this expected behavior.

Snmp_pp::OidCollection oidc;
Snmp_pp::TargetCollection targetc;
status = snmp.notify_register(oidc,targetc,static_my_callback,NULL);

I then attempted to modify the code by appending and Oid object to the OidCollection Object to see if it would allow this trap notification to be processed.


Snmp_pp::OidCollection oidc;
oidc += Snmp_pp::Oid("1.2.3.4.5.6.0.7");
Snmp_pp::TargetCollection targetc;
status = snmp.notify_register(oidc,targetc,static_my_callback,NULL);

However this doesn’t seem to work as expected as no traps appear to be processed.

It is my understanding that the typical trap PDU will consist of:

Here’s a code snippet of my snmp4j agent preparing the trap notification PDU:

pdu.add(new VariableBinding( new Oid("1.3.6.1.2.1.1.3.0"), new OctetString("4:06:20.44") ));
pdu.add(new VariableBinding( new Oid("1.3.6.1.6.3.1.1.5"), new OctetString("1.2.3.4.5.6.0.7") ));
pdu.add(new VariableBinding( new Oid("1.2.3.4.5.6.7.0"), new OctetString("Hello_World") ));

I am wondering if I can get some explaination how this OidCollection is expected to behave and how to get it to filter for trap notification that I provide it?

Hi,

the filter filters the received trap Pdu only on the value of pdu.get_notify_id(trapid);.

A filter for the trap produced by the snmpTraps.cpp example would need to set one Oid of the OidCollection to 1.3.6.1.4.1.11.2.16.2.

Kind regards,
Jochen

Okay so the callback function will always be invoked, but the actual filtering occurs in the callback?
A trivial code example would be something like this?

void TrapReciever::static_my_callback(int reason, Snmp_pp::Snmp snmp*, Snmp_pp::Pdu &pdu, Snmp_pp::SnmpTarget &target, void *cd)
{
bool status;
Snmp_pp::oid id;
status = pdu.get_notify_id(id);
if(status)
{
//Do processing
.}
}

So lets say that a single PDU carries multiple variable bindings inside.

The first variable binding will always be a time stamp
pdu.add(new VariableBinding( new Oid("1.3.6.1.2.1.1.3.0"), new OctetString("4:06:20.44") ));

The second variable binding will always be SnmpTrapOid which contains the actual trap Oid Address specified in its MIB documentation.
pdu.add(new VariableBinding( new Oid("1.3.6.1.6.3.1.1.4.1"), new OctetString("1.2.3.4.5.6.0.7") ));

The 3rd-nth variable binding will be the oid and its value that needs to be processed.
pdu.add(new VariableBinding( new Oid("1.2.3.4.5.6.7.0"), new OctetString("Hello_World") ));
pdu.add(new VariableBinding( new Oid("1.2.3.4.5.6.8.0"), new OctetString("Hello_World1") ));
pdu.add(new VariableBinding( new Oid(" 1.3.6.1.4.1.11.2.16.2"), new OctetString("Hello_World2") ));

My questions are:

  • Does the filter only take into consideration of the first variable binding in the PDU
oidc += Snmp_pp::Oid("1.3.6.1.2.1.1.3.0");
  • Does the filter use the 1.3.6.1.6.3.1.1.4. Oid address’s value to use a filter,
oidc += Snmp_pp::Oid("1.2.3.4.5.6.0.7");
  • Or does the filter take into consideration all values in the pdu?
oidc += Snmp_pp::Oid("1.3.6.1.2.1.1.3.0");
oidc += Snmp_pp::Oid("1.2.3.4.5.6.0.7");
oidc += Snmp_pp::Oid("1.2.3.4.5.6.7.0");
oidc += Snmp_pp::Oid("1.2.3.4.5.6.8.0");
oidc += Snmp_pp::Oid(" 1.3.6.1.4.1.11.2.16.2");
  • What if i were to want to use the TargetCollection to use as a filter?

Hi,

if you are setting a OidCollection, the received Pdus are filtered before your callback is called. The code inside snmp++ does something like this for filtering using OidCollection:

  Oid trapid;
  pdu.get_notify_id(trapid); // pdu is the received Pdu
  if (oidCollection.contains(trapid))
     do_the_user_callback();
  else
    drop_the_pdu(); 

In your callback function, you can of course do some additional filtering. In your example the code of snmp++ can only filter on the SnmpTrapOid, as this Oid is set on the Pdu using Pdu::set_notify_id().

If you set both (OidCollection and TargetCollection), your callback will be called if one of the filters matches. The TargetCollection filter will check for the source address (including port if you use UdpAddress), SNMP version and community.

Kind regards,
Jochen