Tutorial for Visual xAgentBuilder for C++
Lesson 12: Notifications
In this lesson we are going to show how to configure agent to send notifications and how to receive responses to inform requests. While one can argue that inform request is intended for inter-manager notifications, there are cases where dual role entities are required, i.e. entities that assume both manager and agent role.
Sending notifications is easy. All you have to do is, create trap object and pass it to the Trap Sender. Based on configuration Trap Sender will determine where that notification should go and what type of notification should be sent (trap and/or inform).
To create trap object you should create trap class first by deriving from either BTrapV1 (in case trap is defined in SMIv1 MIB module) or from BTrapV2 (if notification definition is from SMIv2 MIB module). Here is the example
class TrapNotPaidAlarm : public BTrapV2
{
public:
TrapNotPaidAlarm()
: BTrapV2(“1.3.6.1.4.1.4761.99.11.2.1”)
{
vbl.Append(BObjectIdentifier(“1.3.6.1.4.1.4761.99.11.1.3.1.2”));
}
TrapNotPaidAlarm(const TrapNotPaidAlarm& t)
: BTrapV2(t)
{}
~TrapNotPaidAlarm()
{}
BTrap* Clone() const
{
return new TrapNotPaidAlarm(*this);
}
void SetValue(tInt32 rowIx, const
BOctetString& vehicleLicencePlate)
{
BVarBind& vb1 = vbl[0];
vb1.Oid().Append(rowIx);
vb1.Value().SetOctets(vehicleLicencePlate);
}
};
Please note that the xAgentBuilder will generate such class from the MIB definition except for the body of the SetValue method.
Implementation of the SetValue method depends on the list of variables/objects that are part of the trap’s varbind list. In this example notPaidAlarm requires single variable in the vblist. The varbind list is initialized in the constructor, but only partial oid is added to the varbind. The variable (vehicleLicencePlate) is columnar object and we should supply the index of the row to make it a correct instance. This is the purpose of the first argument in the SetValue method. The second parameter is the variable’s value. Here is the example:
TrapNotPaidAlarm trap;
trap.SetValue(1, “333 NNN”);
To send trap we simply call:
trapSender.SendTrap(trap);
Who is trapSender?
Trap sender is every agent that implements ITrapSender
interface. ITrapSender
interface defines single method:
void SendTrap(const BTrap& trap, const
tChar* pszParam=NULL);
BSNMPAgent
and BWebAgent are derived from
BAgent class, which is in turn
derived from ITrapSender. In
other words, both SNMP and HTTP agents are trap senders
. . .
BSNMPAgent snmpAgent(tm, &mh, &nv, NULL);
snmpAgent.SendTrap(trap);
BWebAgent webAgent(tm, &mh, &nv);
webAgent.SendTrap(trap);
// actually implementation of SendTrap in BWebAgent
class
// does nothing so the code above has no effect
. . .
BAgents
class is derived from ITrapSender
too. Implementation of the BAgent’s
SendTrap simply calls SendTrap in each registered agent if
pszParam is NULL (default), or only on the agent
registered with the name passed in pszParam.
. . .
BAgents agents(tm);
BSNMPAgent snmpAgent(tm, &mh, &nv, NULL);
agents.Register(“SNMP”, &snmpAgent);
BWebAgent webAgent(tm, &mh, &nv);
agents.Register(“HTTP”, &webAgent);
. . .
// calls SendTrap in both snmpAgent & webAgent
agents.SendTrap(trap);
// calls SendTrap only in snmpAgent
agents.SendTrap(trap, “SNMP”);
// following call has no effect since there is no
agent registered
// with name “MyAgent”
agents.SendTrap(trap, “MyAgent”);
It is very important to understand that sending traps
depends on configuration. As we’ve mentioned HTTP agent (BWebAgent class) does not send
traps, the following applies to SNMP agent only. SNMP Agent can be started as
v1, v2c or v3 agent. The version should be specified in [SNMP Agent] section of the
configuration file:
[SNMP Agent]
Version=SNMPv3(3)
. . .
Possible values are SNMPv1(0),
SNMPv2c(1) and SNMPv3(3). If the value is missing
agent will initialize in SNMPv2c
mode.
The important thing is to understand that different sections of the configuration file are used for sending notifications when agent is started in v1/v2c mode and when it is started in v3 mode.
Note that v1 agent (agent started in SNMPv1 mode) can only send v1 trap pdus and it’ll send only to destinations that are SNMPv1 trap receivers.
v2 agent can send v1 and v2 trap pdus and also informs to destinations that are either SNMPv1
or SNMPv2c trap receivers (if v2 trap or inform is to be sent to SNMPv1 trap receiver it wil lbe converted to v1 trap, similarly if v1 trap pdu is to be sent to SNMPv2c trap receiver it will be converted.
V3 agent can send v1 and v2 trap pdus and also informs to destinations that are SNMPv1,
SNMPv2c or SNMPv3 trap receivers (the conversion will be applied to trap/inform pdu if necessary).
SNMP Agent Started in SNMPv1/SNMPv2c Mode
Destinations for the notifications are listed in v1v2cTargetAddrTbl. The type of the notification is specified in v1v2cNotifyTbl.
How are these two tables linked?
The mechanism used is simple. Notify table specifies pairs (tag, notifType). NotifType is either trap(1) or inform(2). Note that (1) in trap(1) does not mean SNMPv1, it is simply numerical value that specifies trap type. Most of the columns in Target address table are self-descriptive (address, timeout, retryCount, community, version). The specific one is tagList. “tagList” column from Target address table along with the “tag” column from Notify table are used to select targets and type of the notification to send.
Lets show an example:
[v1v2cTargetAddrTbl]
; name address timeout retries tagList community version
1=t1 192.2.1.51:162 5 0 tag1 public SNMPv1(0)
2=t2 BG070:162 5 0 “tag1 tag2” private SNMPv2c(1)
3=t3 ACCOUNTING1:4162 5 0 office public SNMPv2c(1)
[v1v2cNotifyTbl]
; notifyTag
notifyType
1=tag1 trap(1)
2=tag2 inform(2)
3=router inform(2)
To send notification, notification originator subsystem of the SNMP agent will perform the following steps. For each row in the Notify table it’ll try to select targets from the Target address table. Selection happens when tagList in the Target address row contains tag from the Notify table.
For example, the 1st row in Notify table specifies tag “tag1”. Rows 1 and 2 of the target address table contain this tag in the tagList. In other words, trap will be sent to addresses 192.2.1.51:162 and BG070:162. The version of the SNMP message to send and which community string to use will be taken from the corresponding community and version columns. The first destination, 192.2.1.51:162, is specified as SNMPv1 so v1trap pdu will be sent to it. The second destination, BG070:162, has SNMPv2c in the version column, so conversion has to take place: v1Trap generated in Notify will be converted to v2trap pdu and SNMPv2c message containing this v2trap pdu will be sent.
The second row in Notify table contains “tag2” tag that selects the second row in the Target address table. The type of the notification is inform. But in this case v2trap will be sent instead. The reason is the version of the Notify method we’ve used.
The last row in the Notify table will not select anything in the Target address table. There is no row in the Target address table that has “router” tag in the tagList.
As, you have seen, no notification is sent to ACCOUNTING1:4162 since the tagList for that address contains “office” tag which does not appear in any row of Notify table.
SNMP Agent Started in SNMPv3 Mode
SNMP entity (agent, manager) implements SNMP-TARGET-MIB and SNMP-NOTIFICATION-MIB. SNMP-TARGET-MIB defines two tables: snmpTargetAddrTable and snmpTargetParamsTable. The second one defines parameters for v3 messages. Each row in the first one describes
destination address for notification, and contains tag list. Tag list is a set of tags separated by space or tab character. Tag list ties snmpTargetAddrTable to snmpNotifyTable defined in SNMP-NOTIFICATION-MIB. Rows in snmpNotifyTable contain, among others, tag and type columns.
Sending of notifications includes steps for preparing the message, and then selecting destinations. Destination selection is very simple (if we don’t want to perform custom filtering). Basically, for each row in the snmpNotifyTable, corresponding type of notification message is prepared, and then using tag, destination addresses are selected from snmpTargetAddrTable. They are addresses from the rows whose taglist contains tag from the snmpNotifyTable. Parameters for the message are then read from the snmpTargetParamsTable, using the row whose name matches params column in snmpTargetAddrTable.
Lets show an example (only columns of interest are shown):
snmpTargetAddrTable
address tag list params
———— ——————— ———
192.168.1.2:162 “public admin router” p1
192.168.1.8:162 “public” p2
192.168.1.12:4762 “admin public” p1
192.168.1.59:162 “router” p1
snmpTargetParamTable
name MPmodel securityName
—— ——– ———
p1 SNMPv3 initial
p2 SNMPv3 bob
snmpNotifyTable
tag type
——– ———
public trap
router inform
In this configuration, when conditions for the notification to be sent are met, following set of events occurs. For the first row in snmpNotifyTable trap pdu is created and sent to all addresses in snmpTargetAddrTable that have “public” in the tag list. They are “192.168.1.2”, “192.168.1.8”, and “192.168.1.12”. For the second row in snmpNotifyTable inform pdu is created and sent to all addresses in snmpTargetAddrTable that have “router” in the tag list. They are “192.168.1.2”, and “192.168.1.59”. All together five messages are sent. Mesasges sent to “192.168.1.2” are prepared using parameter from “p1” row in snmpTargetParamsTable since the row for the “192.168.1.2” in snmpTargetAddrTable contains “p1” in the params column.
Here is the excerpt from the configuration file:
[v3SnmpTargetAddrTable]
1=t1 udpDomain(1) 127.0.0.1:162 5 0 tag1 p1 nonVolatile(3) active(1)
[v3SnmpTargetParamsTable]
1=p1 SNMPv3(3) USM(3) initial noAuthNoPriv(1) nonVolatile(3) active(1)
[v3SnmpNotifyTable]
1=n1 tag1 trap(1) nonVolatile(3) active(1)