SNMPSET. Particular care should be taken here for two reasons.
Firstly, any errors in the earlier sections can have limited effect. The worst that is likely to happen is that the agent will either return invalid information, or possibly crash. Either way, this is unlikely to affect the operation of the workstation as a whole. If there are problems in the writing routine, the results could be catastrophic (particularly if writing data directly into kernel memory).
Secondly, this is the least well understood area of the agent, at least
by the author. There are relatively few variables that are defined as
READ-WRITE in the relevant MIBs, and even fewer that have
actually been implemented as such.
I'm therefore describing this from a combination of my understanding of
how SETs ought to work, personal experience of very simple SET handling
and what's actually been done by others (which do not necessarily coincide).
There are also subtle differences between the setting of simple scalar variables (or individual entries within a table), and the creation of a new row within a table. This will therefore be considered separately.
With these caveats, and a healthy dose of caution, let us proceed. Note that the UCD-SNMP development team can accept no responsibility for any damage or loss resulting from either following or ignoring the information presented here. You coded it - you fix it!
N.B: The API for the write routine changed slightly between the 3.x and 4.x releases of the UCD agent. In particular, the value to be set was still ASN1-encoded in the 3.x agent, but was directly available as a normal value in the 4.x line. This was a side effect of other internal changes, but was also felt to provide a significantly easier environment with which to work. We apologise for the inconvenience, but refunds are not available :-)
write_methodparameter from the variable handling routine. This is a pointer to the relevant routine for setting the variable in question.
Mib2cwill generate one such routine for each setable variable. This routine should be declared using the template
int write_variable( int action, u_char *var_val, u_char var_val_type, int var_val_len, u_char *statP, oid *name, int name_len );
Most of these parameters are fairly self explanatory:
The last two hold the OID to be set, just as was passed to the main variable routine.
The second, third and fourth parameters provide information about the new desired value, both the type, value and length. This is very similar to the way that results are returned from the main variable routine.
The return value of the routine is simply an indication of whether the current stage of the SET was successful or not. We'll come back to this in a minute. Note that it is the responsibility of this routine to check that the OID and value provided are appropriate for the variable being implemented. This includes (but is not limited to) checking:
The fifth parameter,
statP, is the value that would
be returned from a
GET request on this particular variable.
It could be used to check that the requested new value is
consistent with the current state, but its main use is to denote that
a new table row is being created.
In most cases (particularly when dealing with scalar values or single
elements of tables), you can normally simply ignore this parameter.
action. To understand this, it's necessary to know a bit about how SETs are implemented.
This is implemented using three basic phases:
RESERVE is used to check the syntax of all the variables provided,
that the values being set are sensible and consistent,
and to allocate any resources required for performing the SET.
After this stage, the expectation is that the SET ought to succeed,
though this is not guaranteed.
(In fact, with the UCD agent, this is done in two passes -
RESERVE2, to allow for dependencies between variables).
If any of these calls fail (in either pass)
the write routines are called again with the
to release any resources that have been allocated. The agent will then return
a failure response to the requesting application.
Assuming that the
RESERVE phase was successful,
the next stage is indicated by the action value
This is used to actually implement the set
operation. However, this must either be done into temporary (persistent)
storage, or the previous value stored in a similar way, in case any of the
ACTION calls fail.
This can be seen in the example module, where both write routines have static
'old' variables, to hold the previous value of the relevant object.
ACTION phase does fail (for example due to an apparently valid, but unacceptable
value, or an unforeseen problem), then the list of write routines are
called again, with the
UNDO action. This requires the routine to reset
the value that was changed to its previous value (assuming it was actually
changed), and then to release any resources that had been allocated.
As with the
FREE phase, the agent will then return an indication of the error
to the requesting application.
Only once the
ACTION phase has completed successfully, can the final
COMMIT phase be run.
This is used to complete any writes that were done
into temporary storage, and then release any allocated resources.
Note that all the code in this phase should be "safe" code that cannot possibly
fail (cue hysterical laughter).
The whole intent of the
is that all of the fallible code should be done in the
so that it can be backed out if necessary.
GETrequest would have failed, and hence the fifth parameter,
statP, will be null. This contrasts with changing the values of an element of an existing row, when the
statPparameter would hold the previous value.
The details of precisely how to create a new row will clearly depend on the underlying format of the table. However, one implementation strategy would be as follows:
SETwould return a null value from the var_name routine. This null
statPparameter would be the signal to create a new temporary instance of the underlying data structure, filled with dummy values.
SET, the completed temporary instance could be moved into the "standard" structure (or copied, or otherwise used to set things up appropriately).
SETrequests. Anyone who has experience of doing this, please get in touch!
And if you've found this helpful, gifts of money, chocolate, alcohol, and above all feedback, would be most appreciated :-)