1
#include <net-snmp/net-snmp-config.h>
2
#include <net-snmp/net-snmp-includes.h>
3
#include <net-snmp/agent/net-snmp-agent-includes.h>
4
#include <net-snmp/agent/scalar.h>
12
#include <net-snmp/library/snmp_logging.h>
13
#include "agent/nsLogging.h"
14
#include "util_funcs.h"
19
* OID and columns for the logging table.
22
#define NSLOGGING_TYPE 3
23
#define NSLOGGING_MAXLEVEL 4
24
#define NSLOGGING_STATUS 5
26
oid nsLoggingTable_oid[] = { 1, 3, 6, 1, 4, 1, 8072, 1, 7, 2, 1};
32
netsnmp_table_registration_info *table_info;
33
netsnmp_iterator_info *iinfo;
37
* We need to define the column structure and indexing....
40
table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
44
netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER,
45
ASN_PRIV_IMPLIED_OCTET_STR, 0);
46
table_info->min_column = NSLOGGING_TYPE;
47
table_info->max_column = NSLOGGING_STATUS;
51
* .... and the iteration information ....
53
iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
57
iinfo->get_first_data_point = get_first_logging_entry;
58
iinfo->get_next_data_point = get_next_logging_entry;
59
iinfo->table_reginfo = table_info;
63
* .... and register the table with the agent.
65
netsnmp_register_table_iterator(
66
netsnmp_create_handler_registration(
67
"tzLoggingTable", handle_nsLoggingTable,
68
nsLoggingTable_oid, OID_LENGTH(nsLoggingTable_oid),
75
* nsLoggingTable handling
78
netsnmp_variable_list *
79
get_first_logging_entry(void **loop_context, void **data_context,
80
netsnmp_variable_list *index,
81
netsnmp_iterator_info *data)
83
netsnmp_log_handler *logh_head = get_logh_head();
87
snmp_set_var_value(index, (u_char*)&logh_head->priority,
88
sizeof(logh_head->priority));
89
if ( logh_head->token )
90
snmp_set_var_value(index->next_variable, (const u_char*)logh_head->token,
91
strlen(logh_head->token));
93
snmp_set_var_value(index->next_variable, NULL, 0);
94
*loop_context = (void*)logh_head;
95
*data_context = (void*)logh_head;
99
netsnmp_variable_list *
100
get_next_logging_entry(void **loop_context, void **data_context,
101
netsnmp_variable_list *index,
102
netsnmp_iterator_info *data)
104
netsnmp_log_handler *logh = (netsnmp_log_handler *)*loop_context;
110
snmp_set_var_value(index, (u_char*)&logh->priority,
111
sizeof(logh->priority));
113
snmp_set_var_value(index->next_variable, (const u_char*)logh->token,
114
strlen(logh->token));
116
snmp_set_var_value(index->next_variable, NULL, 0);
117
*loop_context = (void*)logh;
118
*data_context = (void*)logh;
124
handle_nsLoggingTable(netsnmp_mib_handler *handler,
125
netsnmp_handler_registration *reginfo,
126
netsnmp_agent_request_info *reqinfo,
127
netsnmp_request_info *requests)
130
netsnmp_request_info *request = NULL;
131
netsnmp_table_request_info *table_info = NULL;
132
netsnmp_log_handler *logh = NULL;
133
netsnmp_variable_list *idx = NULL;
135
switch (reqinfo->mode) {
138
for (request=requests; request; request=request->next) {
139
if (requests->processed != 0)
141
logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
142
table_info = netsnmp_extract_table_info(request);
144
switch (table_info->colnum) {
147
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
150
snmp_set_var_typed_value(request->requestvb, ASN_INTEGER,
151
(u_char*)&logh->type,
155
case NSLOGGING_MAXLEVEL:
157
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
160
snmp_set_var_typed_value(request->requestvb, ASN_INTEGER,
161
(u_char*)&logh->pri_max,
162
sizeof(logh->pri_max));
165
case NSLOGGING_STATUS:
167
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
170
status = (logh->type ?
175
snmp_set_var_typed_value(request->requestvb, ASN_INTEGER,
176
(u_char*)&status, sizeof(status));
180
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
187
case MODE_SET_RESERVE1:
188
for (request=requests; request; request=request->next) {
189
if ( request->status != 0 ) {
190
return SNMP_ERR_NOERROR; /* Already got an error */
192
logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
193
table_info = netsnmp_extract_table_info(request);
195
switch (table_info->colnum) {
197
if ( request->requestvb->type != ASN_INTEGER ) {
198
netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE);
199
return SNMP_ERR_WRONGTYPE;
201
if (*request->requestvb->val.integer < 0 ) {
202
netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE);
203
return SNMP_ERR_WRONGVALUE;
206
* It's OK to create a new logging entry
207
* (either in one go, or built up using createAndWait)
208
* but it's not possible to change the type of an entry
209
* once it's been created.
211
if (logh && logh->type) {
212
netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOTWRITABLE);
213
return SNMP_ERR_NOTWRITABLE;
217
case NSLOGGING_MAXLEVEL:
218
if ( request->requestvb->type != ASN_INTEGER ) {
219
netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE);
220
return SNMP_ERR_WRONGTYPE;
222
if (*request->requestvb->val.integer < 0 ||
223
*request->requestvb->val.integer > 7 ) {
224
netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE);
225
return SNMP_ERR_WRONGVALUE;
229
case NSLOGGING_STATUS:
230
if ( request->requestvb->type != ASN_INTEGER ) {
231
netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE);
232
return SNMP_ERR_WRONGTYPE;
234
status = *request->requestvb->val.integer;
237
case RS_NOTINSERVICE:
239
* Can only work on existing rows
242
netsnmp_set_request_error(reqinfo, request,
243
SNMP_ERR_INCONSISTENTVALUE);
244
return SNMP_ERR_INCONSISTENTVALUE;
248
case RS_CREATEANDWAIT:
251
* Can only work with new rows
254
netsnmp_set_request_error(reqinfo, request,
255
SNMP_ERR_INCONSISTENTVALUE);
256
return SNMP_ERR_INCONSISTENTVALUE;
260
* Normally, we'd create the row at a later stage
261
* (probably during the RESERVE2 or ACTION passes)
263
* But we need to check that the values are
264
* consistent during the ACTION pass (which is the
265
* latest that an error can be safely handled),
266
* so the values all need to be set up before this
267
* (i.e. during the RESERVE2 pass)
268
* So the new row needs to be created before that
269
* in order to have somewhere to put them.
271
* That's why we're doing this here.
273
idx = table_info->indexes;
274
logh = netsnmp_register_loghandler(
275
/* not really, but we need a valid type */
276
NETSNMP_LOGHANDLER_STDOUT,
279
netsnmp_set_request_error(reqinfo, request,
280
SNMP_ERR_GENERR); /* ??? */
281
return SNMP_ERR_GENERR;
283
idx = idx->next_variable;
285
logh->token = strdup(idx->val.string);
286
netsnmp_insert_iterator_context(request, (void*)logh);
291
* Can work with new or existing rows
297
netsnmp_set_request_error(reqinfo, request,
298
SNMP_ERR_WRONGVALUE);
299
return SNMP_ERR_WRONGVALUE;
304
netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
305
return SNMP_NOSUCHOBJECT;
312
case MODE_SET_RESERVE2:
313
for (request=requests; request; request=request->next) {
314
if ( request->status != 0 ) {
315
return SNMP_ERR_NOERROR; /* Already got an error */
317
logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
318
table_info = netsnmp_extract_table_info(request);
320
switch (table_info->colnum) {
323
* If we're creating a row using createAndGo,
324
* we need to set the type early, so that we
325
* can validate it in the ACTION pass.
327
* Remember that we need to be able to reverse this
330
logh->type = *request->requestvb->val.integer;
333
* Don't need to handle nsLogToken or nsLogStatus in this pass
339
case MODE_SET_ACTION:
340
for (request=requests; request; request=request->next) {
341
if (requests->processed != 0)
343
if ( request->status != 0 ) {
344
return SNMP_ERR_NOERROR; /* Already got an error */
346
logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
347
table_info = netsnmp_extract_table_info(request);
349
switch (table_info->colnum) {
350
case NSLOGGING_STATUS:
352
* This is where we can check the internal consistency
353
* of the request. Basically, for a row to be marked
354
* 'active', then there needs to be a valid type value.
356
status = *request->requestvb->val.integer;
361
netsnmp_set_request_error(reqinfo, request,
362
SNMP_ERR_INCONSISTENTVALUE);
363
return SNMP_ERR_INCONSISTENTVALUE;
369
* Don't need to handle nsLogToken or nsLogType in this pass
378
* If any resources were allocated in either of the
379
* two RESERVE passes, they need to be released here,
380
* and any assignments (in RESERVE2) reversed.
382
* Nothing additional will have been done during ACTION
383
* so this same code can do for UNDO as well.
385
for (request=requests; request; request=request->next) {
386
if (requests->processed != 0)
388
logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
389
table_info = netsnmp_extract_table_info(request);
391
switch (table_info->colnum) {
394
* If we've been setting the type, and the request
395
* has failed, then revert to an unset type.
397
* We need to be careful here - if the reason it failed is
398
* that the type was already set, then we shouldn't "undo"
399
* the assignment (since it won't actually have been made).
401
* Check the current value against the 'new' one. If they're
402
* the same, then this is probably a successful assignment,
403
* and the failure was elsewhere, so we need to undo it.
404
* (Or else there was an attempt to write the same value!)
406
if ( logh && logh->type == *request->requestvb->val.integer )
410
case NSLOGGING_STATUS:
411
status = *request->requestvb->val.integer;
412
if ( logh && ( status == RS_CREATEANDGO ||
413
status == RS_CREATEANDWAIT)) {
414
netsnmp_remove_loghandler( logh );
418
* Don't need to handle nsLogToken in this pass
425
case MODE_SET_COMMIT:
426
for (request=requests; request; request=request->next) {
427
if (requests->processed != 0)
429
if ( request->status != 0 ) {
430
return SNMP_ERR_NOERROR; /* Already got an error */
432
logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
434
netsnmp_set_request_error(reqinfo, request, SNMP_ERR_COMMITFAILED);
435
return SNMP_ERR_COMMITFAILED; /* Shouldn't happen! */
437
table_info = netsnmp_extract_table_info(request);
439
switch (table_info->colnum) {
440
case NSLOGGING_MAXLEVEL:
441
logh->pri_max = *request->requestvb->val.integer;
444
case NSLOGGING_STATUS:
445
switch (*request->requestvb->val.integer) {
450
case RS_NOTINSERVICE:
451
case RS_CREATEANDWAIT:
455
netsnmp_remove_loghandler( logh );
464
return SNMP_ERR_NOERROR;