~ubuntu-branches/ubuntu/trusty/net-snmp/trusty

« back to all changes in this revision

Viewing changes to agent/mibgroup/agent/nsLogging.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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>
 
5
 
 
6
#ifdef HAVE_STRING_H
 
7
#include <string.h>
 
8
#else
 
9
#include <strings.h>
 
10
#endif
 
11
 
 
12
#include <net-snmp/library/snmp_logging.h>
 
13
#include "agent/nsLogging.h"
 
14
#include "util_funcs.h"
 
15
 
 
16
 
 
17
 
 
18
/*
 
19
 * OID and columns for the logging table.
 
20
 */
 
21
 
 
22
#define  NSLOGGING_TYPE         3
 
23
#define  NSLOGGING_MAXLEVEL     4
 
24
#define  NSLOGGING_STATUS       5
 
25
 
 
26
oid nsLoggingTable_oid[]      = { 1, 3, 6, 1, 4, 1, 8072, 1, 7, 2, 1};
 
27
 
 
28
 
 
29
void
 
30
init_nsLogging(void)
 
31
{
 
32
    netsnmp_table_registration_info *table_info;
 
33
    netsnmp_iterator_info           *iinfo;
 
34
 
 
35
    /*
 
36
     * Register the table.
 
37
     * We need to define the column structure and indexing....
 
38
     */
 
39
 
 
40
    table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
 
41
    if (!table_info) {
 
42
        return;
 
43
    }
 
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;
 
48
 
 
49
 
 
50
    /*
 
51
     * .... and the iteration information ....
 
52
     */
 
53
    iinfo      = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
 
54
    if (!iinfo) {
 
55
        return;
 
56
    }
 
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;
 
60
 
 
61
 
 
62
    /*
 
63
     * .... and register the table with the agent.
 
64
     */
 
65
    netsnmp_register_table_iterator(
 
66
        netsnmp_create_handler_registration(
 
67
            "tzLoggingTable", handle_nsLoggingTable,
 
68
            nsLoggingTable_oid, OID_LENGTH(nsLoggingTable_oid),
 
69
            HANDLER_CAN_RWRITE),
 
70
        iinfo);
 
71
}
 
72
 
 
73
 
 
74
/*
 
75
 * nsLoggingTable handling
 
76
 */
 
77
 
 
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)
 
82
{
 
83
        netsnmp_log_handler  *logh_head = get_logh_head();
 
84
    if ( !logh_head )
 
85
        return NULL;
 
86
 
 
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));
 
92
    else
 
93
        snmp_set_var_value(index->next_variable, NULL, 0);
 
94
    *loop_context = (void*)logh_head;
 
95
    *data_context = (void*)logh_head;
 
96
    return index;
 
97
}
 
98
 
 
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)
 
103
{
 
104
    netsnmp_log_handler *logh = (netsnmp_log_handler *)*loop_context;
 
105
    logh = logh->next;
 
106
 
 
107
    if ( !logh )
 
108
        return NULL;
 
109
 
 
110
    snmp_set_var_value(index, (u_char*)&logh->priority,
 
111
                                 sizeof(logh->priority));
 
112
    if ( logh->token )
 
113
        snmp_set_var_value(index->next_variable, (const u_char*)logh->token,
 
114
                                                   strlen(logh->token));
 
115
    else
 
116
        snmp_set_var_value(index->next_variable, NULL, 0);
 
117
    *loop_context = (void*)logh;
 
118
    *data_context = (void*)logh;
 
119
    return index;
 
120
}
 
121
 
 
122
 
 
123
int
 
124
handle_nsLoggingTable(netsnmp_mib_handler *handler,
 
125
                netsnmp_handler_registration *reginfo,
 
126
                netsnmp_agent_request_info *reqinfo,
 
127
                netsnmp_request_info *requests)
 
128
{
 
129
    long status;
 
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;
 
134
 
 
135
    switch (reqinfo->mode) {
 
136
 
 
137
    case MODE_GET:
 
138
        for (request=requests; request; request=request->next) {
 
139
            if (requests->processed != 0)
 
140
                continue;
 
141
            logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
 
142
            table_info  =                netsnmp_extract_table_info(request);
 
143
 
 
144
            switch (table_info->colnum) {
 
145
            case NSLOGGING_TYPE:
 
146
                if (!logh) {
 
147
                    netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
 
148
                    continue;
 
149
                }
 
150
                snmp_set_var_typed_value(request->requestvb, ASN_INTEGER,
 
151
                                         (u_char*)&logh->type,
 
152
                                            sizeof(logh->type));
 
153
                break;
 
154
 
 
155
            case NSLOGGING_MAXLEVEL:
 
156
                if (!logh) {
 
157
                    netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
 
158
                    continue;
 
159
                }
 
160
                snmp_set_var_typed_value(request->requestvb, ASN_INTEGER,
 
161
                                         (u_char*)&logh->pri_max,
 
162
                                            sizeof(logh->pri_max));
 
163
                break;
 
164
 
 
165
            case NSLOGGING_STATUS:
 
166
                if (!logh) {
 
167
                    netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
 
168
                    continue;
 
169
                }
 
170
                status = (logh->type ?
 
171
                           (logh->enabled ?
 
172
                              RS_ACTIVE:
 
173
                              RS_NOTINSERVICE) :
 
174
                            RS_NOTREADY);
 
175
                snmp_set_var_typed_value(request->requestvb, ASN_INTEGER,
 
176
                                         (u_char*)&status, sizeof(status));
 
177
                break;
 
178
 
 
179
            default:
 
180
                netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
 
181
                continue;
 
182
            }
 
183
        }
 
184
        break;
 
185
 
 
186
 
 
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 */
 
191
            }
 
192
            logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
 
193
            table_info  =                 netsnmp_extract_table_info(request);
 
194
 
 
195
            switch (table_info->colnum) {
 
196
            case NSLOGGING_TYPE:
 
197
                if ( request->requestvb->type != ASN_INTEGER ) {
 
198
                    netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE);
 
199
                    return SNMP_ERR_WRONGTYPE;
 
200
                }
 
201
                if (*request->requestvb->val.integer < 0 ) {
 
202
                    netsnmp_set_request_error(reqinfo, request, SNMP_ERR_WRONGVALUE);
 
203
                    return SNMP_ERR_WRONGVALUE;
 
204
                }
 
205
                /*
 
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.
 
210
                 */
 
211
                if (logh && logh->type) {
 
212
                    netsnmp_set_request_error(reqinfo, request, SNMP_ERR_NOTWRITABLE);
 
213
                    return SNMP_ERR_NOTWRITABLE;
 
214
                }
 
215
                break;
 
216
 
 
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;
 
221
                }
 
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;
 
226
                }
 
227
                break;
 
228
 
 
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;
 
233
                }
 
234
                status = *request->requestvb->val.integer;
 
235
                switch ( status ) {
 
236
                case RS_ACTIVE:
 
237
                case RS_NOTINSERVICE:
 
238
                    /*
 
239
                     * Can only work on existing rows
 
240
                     */
 
241
                    if (!logh) {
 
242
                        netsnmp_set_request_error(reqinfo, request,
 
243
                                                  SNMP_ERR_INCONSISTENTVALUE);
 
244
                        return SNMP_ERR_INCONSISTENTVALUE;
 
245
                    }
 
246
                    break;
 
247
 
 
248
                case RS_CREATEANDWAIT:
 
249
                case RS_CREATEANDGO:
 
250
                    /*
 
251
                     * Can only work with new rows
 
252
                     */
 
253
                    if (logh) {
 
254
                        netsnmp_set_request_error(reqinfo, request,
 
255
                                                  SNMP_ERR_INCONSISTENTVALUE);
 
256
                        return SNMP_ERR_INCONSISTENTVALUE;
 
257
                    }
 
258
 
 
259
                    /*
 
260
                     *  Normally, we'd create the row at a later stage
 
261
                     *   (probably during the RESERVE2 or ACTION passes)
 
262
                     *
 
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.
 
270
                     *
 
271
                     *  That's why we're doing this here.
 
272
                     */
 
273
                    idx = table_info->indexes;
 
274
                    logh = netsnmp_register_loghandler(
 
275
                                    /* not really, but we need a valid type */
 
276
                                    NETSNMP_LOGHANDLER_STDOUT,
 
277
                                    *idx->val.integer);
 
278
                    if (!logh) {
 
279
                        netsnmp_set_request_error(reqinfo, request,
 
280
                                                  SNMP_ERR_GENERR); /* ??? */
 
281
                        return SNMP_ERR_GENERR;
 
282
                    }
 
283
                    idx = idx->next_variable;
 
284
                    logh->type  = 0;
 
285
                    logh->token = strdup(idx->val.string);
 
286
                    netsnmp_insert_iterator_context(request, (void*)logh);
 
287
                    break;
 
288
 
 
289
                case RS_DESTROY:
 
290
                    /*
 
291
                     * Can work with new or existing rows
 
292
                     */
 
293
                    break;
 
294
 
 
295
                case RS_NOTREADY:
 
296
                default:
 
297
                    netsnmp_set_request_error(reqinfo, request,
 
298
                                              SNMP_ERR_WRONGVALUE);
 
299
                    return SNMP_ERR_WRONGVALUE;
 
300
                }
 
301
                break;
 
302
 
 
303
            default:
 
304
                netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHOBJECT);
 
305
                return SNMP_NOSUCHOBJECT;
 
306
                continue;
 
307
            }
 
308
        }
 
309
        break;
 
310
 
 
311
 
 
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 */
 
316
            }
 
317
            logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
 
318
            table_info  =                 netsnmp_extract_table_info(request);
 
319
 
 
320
            switch (table_info->colnum) {
 
321
            case NSLOGGING_TYPE:
 
322
                /*
 
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.
 
326
                 *
 
327
                 * Remember that we need to be able to reverse this
 
328
                 */
 
329
                if ( logh )
 
330
                    logh->type = *request->requestvb->val.integer;
 
331
                break;
 
332
            /*
 
333
             * Don't need to handle nsLogToken or nsLogStatus in this pass
 
334
             */
 
335
            }
 
336
        }
 
337
        break;
 
338
 
 
339
    case MODE_SET_ACTION:
 
340
        for (request=requests; request; request=request->next) {
 
341
            if (requests->processed != 0)
 
342
                continue;
 
343
            if ( request->status != 0 ) {
 
344
                return SNMP_ERR_NOERROR;        /* Already got an error */
 
345
            }
 
346
            logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
 
347
            table_info  =                 netsnmp_extract_table_info(request);
 
348
 
 
349
            switch (table_info->colnum) {
 
350
            case NSLOGGING_STATUS:
 
351
                /*
 
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.
 
355
                 */
 
356
                status = *request->requestvb->val.integer;
 
357
                switch ( status ) {
 
358
                case RS_ACTIVE:
 
359
                case RS_CREATEANDGO:
 
360
                    if ( !logh->type ) {
 
361
                        netsnmp_set_request_error(reqinfo, request,
 
362
                                                  SNMP_ERR_INCONSISTENTVALUE);
 
363
                        return SNMP_ERR_INCONSISTENTVALUE;
 
364
                    }
 
365
                    break;
 
366
                }
 
367
                break;
 
368
            /*
 
369
             * Don't need to handle nsLogToken or nsLogType in this pass
 
370
             */
 
371
            }
 
372
        }
 
373
        break;
 
374
 
 
375
    case MODE_SET_FREE:
 
376
    case MODE_SET_UNDO:
 
377
        /*
 
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.
 
381
         *
 
382
         * Nothing additional will have been done during ACTION
 
383
         *  so this same code can do for UNDO as well.
 
384
         */
 
385
        for (request=requests; request; request=request->next) {
 
386
            if (requests->processed != 0)
 
387
                continue;
 
388
            logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
 
389
            table_info  =                 netsnmp_extract_table_info(request);
 
390
 
 
391
            switch (table_info->colnum) {
 
392
            case NSLOGGING_TYPE:
 
393
                /*
 
394
                 * If we've been setting the type, and the request
 
395
                 * has failed, then revert to an unset type.
 
396
                 *
 
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).
 
400
                 *
 
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!)
 
405
                 */
 
406
                if ( logh && logh->type == *request->requestvb->val.integer )
 
407
                    logh->type = 0;
 
408
                break;
 
409
 
 
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 );
 
415
                }
 
416
                break;
 
417
            /*
 
418
             * Don't need to handle nsLogToken in this pass
 
419
             */
 
420
            }
 
421
        }
 
422
        break;
 
423
 
 
424
 
 
425
    case MODE_SET_COMMIT:
 
426
        for (request=requests; request; request=request->next) {
 
427
            if (requests->processed != 0)
 
428
                continue;
 
429
            if ( request->status != 0 ) {
 
430
                return SNMP_ERR_NOERROR;        /* Already got an error */
 
431
            }
 
432
            logh = (netsnmp_log_handler*)netsnmp_extract_iterator_context(request);
 
433
            if (!logh) {
 
434
                netsnmp_set_request_error(reqinfo, request, SNMP_ERR_COMMITFAILED);
 
435
                return SNMP_ERR_COMMITFAILED;   /* Shouldn't happen! */
 
436
            }
 
437
            table_info  =                 netsnmp_extract_table_info(request);
 
438
 
 
439
            switch (table_info->colnum) {
 
440
            case NSLOGGING_MAXLEVEL:
 
441
                logh->pri_max = *request->requestvb->val.integer;
 
442
                break;
 
443
 
 
444
            case NSLOGGING_STATUS:
 
445
                switch (*request->requestvb->val.integer) {
 
446
                    case RS_ACTIVE:
 
447
                    case RS_CREATEANDGO:
 
448
                        logh->enabled = 1;
 
449
                        break;
 
450
                    case RS_NOTINSERVICE:
 
451
                    case RS_CREATEANDWAIT:
 
452
                        logh->enabled = 0;
 
453
                        break;
 
454
                    case RS_DESTROY:
 
455
                        netsnmp_remove_loghandler( logh );
 
456
                        break;
 
457
                }
 
458
                break;
 
459
            }
 
460
        }
 
461
        break;
 
462
    }
 
463
 
 
464
    return SNMP_ERR_NOERROR;
 
465
}