|
|
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;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: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);
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.