|
|
When xselect indicates the SMUX file descriptor is ready for reading, the peer program calls the routine smux_wait to return the next event from the SNMP agent.
The event is filled-in from a static area. On the next call to smux_init, smux_close, or smux_wait, the value is overwritten.
On failure, smux_errno will be set to one of parameterMissing, invalidOperation, inProgress, or youLoseBig. See ``Error recovery'' for an explanation of these error codes. The peer program takes the appropriate action based on the error code returned.
struct type_SNMP_SMUX__PDUs *event;Next, the peer program switches based on the actual event returned:if (smux_wait(&event, NOTOK) == NOTOK) { if (smux_errno == inProgress) return;
LIB_ERROR2("smux_wait: %s [%s]", smux_error(smux_errno), smux_info); smux_fd = NOTOK; return; }
SMUX__PDUs_registerResponse SMUX__PDUs_get__request SMUX__PDUs_get__next__request SMUX__PDUs_set__request SMUX__PDUs_commitOrRollback SMUX__PDUs_closeThe actual code is fairly straightforward:
switch (event->offset) {
case SMUX__PDUs_registerResponse:
if (!tc->t_name)
goto unexpected;
{
struct type_SNMP_RRspPDU *rsp = event->un.registerResponse;
if (rsp->parm == RRspPDU_failure)
LIB_ERROR1("SMUX registration of %s failed\n", tc->t_tree);
else {
if (debug)
printf("SMUX register: %s out=%d\n", tc->t_tree, rsp->parm);
got_at_least_one = 1;
}
}
for (tc++; tc->t_tree; tc++)
if (tc->t_name) {
if (smux_register(tc->t_name, -1, tc->t_access)
== NOTOK) {
LIB_ERROR2("smux_register: %s [%s]\n",
smux_error(smux_errno), smux_info);
goto losing;
}
if (debug)
printf("SMUX register: %s in=%d\n", tc->t_tree, -1);
break;
}
if (!tc->t_tree) {
if (!got_at_least_one) {
dont_bother_anymore = 1;
(void) smux_close(goingDown);
goto losing;
}
if (smux_trap(trap_coldStart, 0,
(struct type_SNMP_VarBindList *) 0) == NOTOK) {
LIB_ERROR2("smux_trap: %s [%s]", smux_error(smux_errno),
smux_info);
goto losing;
}
}
break;
case SMUX__PDUs_get__request:
case SMUX__PDUs_get__next__request:
case SMUX__PDUs_set__request:
do_smux(event->un.get__request, event->offset);
break;
case SMUX__PDUs_commitOrRollback:
{
register struct triple *tz;
for (tz = triples; tz->t_tree; tz++)
if (tz->t_name)
(void) (*tz->t_sync) (event->un.commitOrRollback->parm);
}
break;
case SMUX__PDUs_close:
if (debug)
printf("SMUX close: %s\n", smux_error(event->un.close->parm));
goto losing;
case SMUX__PDUs_simple:
case SMUX__PDUs_registerRequest:
case SMUX__PDUs_get__response:
case SMUX__PDUs_trap:
unexpected: ;
LIB_ERROR1("unexpectedOperation: %d", event->offset);
(void) smux_close(protocolError);
goto losing;
default:
LIB_ERROR1("badOperation: %d", event->offset);
(void) smux_close(protocolError);
goto losing;
}
free_SNMP_SMUX_PDU(event);
Note the use of the smux_trap routine
to send a coldStart trap
once the peer has successfully registered the
MIB module it will be managing.
The trap codes are:
trap_coldStart trap_warmStart trap_linkDown trap_linkUp trap_authenticationFailure trap_egpNeighborLoss trap_enterpriseSpecificIf this routine fails, smux_errno will be set to one of invalidOperation, congestion, or youLoseBig.