Developing SMUX peers for SNMP agents

Get and set

When xselect indicates the SMUX file descriptor is ready for reading, the reference peer program calls the routine smux_wait to return the next event from the SNMP agent. The peer program invoked The routine do_smux, which implements the SNMP ``get'', ``get-next'' and ``set'' operations. The routine looks like this:

   do_smux(pdu, offset)
       register struct type_SNMP_GetRequest__PDU *pdu;
       int             offset;
       int             idx, status;
       object_instance ois;
       register struct type_SNMP_VarBindList *vp;
       IFP             method;

quantum = pdu->request__id; idx = 0; for (vp = pdu->variable__bindings; vp; vp = vp->next) { register OI oi; register OT ot; register struct type_SNMP_VarBind *v = vp->VarBind;


if (offset == SMUX__PDUs_get__next__request) { if ((oi = name2inst(v->name)) == NULLOI && (oi = next2inst(v->name)) == NULLOI) goto no_name;

if ((ot = oi->oi_type)->ot_getfnx == NULLIFP) goto get_next; } else { if ((oi = name2inst(v->name)) == NULLOI) goto no_name; ot = oi->oi_type; if ((offset == SMUX__PDUs_get__request ? ot->ot_getfnx : ot->ot_setfnx) == NULLIFP) { no_name: ; pdu->error__status = error__status_noSuchName; goto out; } }


try_again: ; switch (offset) { case SMUX__PDUs_get__request: if (!(method = ot->ot_getfnx)) goto no_name; break;

case SMUX__PDUs_get__next__request: if (!(method = ot->ot_getfnx)) goto get_next; break;

case SMUX__PDUs_set__request: if (!(method = ot->ot_setfnx)) goto no_name; break;

default: goto no_name; }

           switch (status = (method) (oi, v, offset)) {
           case NOTOK:    /* get-next wants a bump */
       get_next:    ;
               oi = &ois ;
               for (;;) {
                   if ((ot = ot->ot_next) == NULLOT) {
                       pdu->error__status = error__status_noSuchName;
                       goto out;
                   oi->oi_name = (oi->oi_type = ot)->ot_name;
                   if (ot->ot_getfnx)
                       goto try_again;

           case error__status_noError:

default: pdu->error__status = status; goto out; } } idx = 0;

out: ; pdu->error__index = idx;

if (smux_response(pdu) == NOTOK) { LIB_ERROR2("smux_response: %s [%s]", smux_error(smux_errno), smux_info); smux_fd = NOTOK; } }

The actual code is fairly straightforward. First, the variable quantum is set to the request ID for this transaction. The SMUX protocol requires that this number increment for each SNMP operation that the agent handles, so the peer program can use it to see when it should re-read its local variables. (A single SNMP operation received by the agent might result in multiple SMUX protocol transactions with the program.)

Next, the code loops through the list of variables requested. The object instance is determined and loaded into oin and the corresponding object type is loaded into ot, and the access is checked.

Finally, the user-defined routine is invoked. This routine returns one of these values:

NOTOK error__status_noError error__status_tooBig error__status_noSuchName error__status_badValue error__status_readOnly error__status_genErr

The first value is returned only if the get-next operator is being invoked and the routine didn't have any more object instances for the object type in question. The remainder are similar to the error codes returned by the SNMP agent and are self-explanatory.

Once an answer is returned, the loop either continues or is broken and a response is written back using the smux_response routine. On failure, smux_error will be set to one of parameterMissing, invalidOperation, or youLoseBig.

Next topic: Encoding and decoding PDUs
Previous topic: Events

© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003