~ubuntu-branches/debian/lenny/net-snmp/lenny

« back to all changes in this revision

Viewing changes to agent/mibgroup/disman/expr/expValueTable.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-05-10 22:20:23 UTC
  • Revision ID: james.westby@ubuntu.com-20070510222023-3fr07xb9i17xvq32
Tags: upstream-5.3.1
ImportĀ upstreamĀ versionĀ 5.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DisMan Expression MIB:
 
3
 *    Implementation of the expValueTable MIB interface
 
4
 * See 'expValue.c' for active evaluation of expressions.
 
5
 *
 
6
 *  (Based roughly on mib2c.raw-table.conf output)
 
7
 */
 
8
 
 
9
#include <net-snmp/net-snmp-config.h>
 
10
#include <net-snmp/net-snmp-includes.h>
 
11
#include <net-snmp/agent/net-snmp-agent-includes.h>
 
12
#include "expValue.h"
 
13
#include "expValueTable.h"
 
14
 
 
15
/** Initializes the expValueTable module */
 
16
void
 
17
init_expValueTable(void)
 
18
{
 
19
    static oid  expValueTable_oid[]   = { 1, 3, 6, 1, 2, 1, 90, 1, 3, 1 };
 
20
    size_t      expValueTable_oid_len = OID_LENGTH(expValueTable_oid);
 
21
    netsnmp_handler_registration *reg;
 
22
    netsnmp_table_registration_info *table_info;
 
23
 
 
24
    reg =
 
25
        netsnmp_create_handler_registration("expValueTable",
 
26
                                            expValueTable_handler,
 
27
                                            expValueTable_oid,
 
28
                                            expValueTable_oid_len,
 
29
                                            HANDLER_CAN_RONLY);
 
30
 
 
31
    table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
 
32
    netsnmp_table_helper_add_indexes(table_info,
 
33
                                     ASN_OCTET_STR, /* expExpressionOwner */
 
34
                                     ASN_OCTET_STR, /* expExpressionName  */
 
35
                                                    /* expValueInstance   */
 
36
                                     ASN_PRIV_IMPLIED_OBJECT_ID,
 
37
                                     0);
 
38
 
 
39
    table_info->min_column = COLUMN_EXPVALUECOUNTER32VAL;
 
40
    table_info->max_column = COLUMN_EXPVALUECOUNTER64VAL;
 
41
 
 
42
    netsnmp_register_table(reg, table_info);
 
43
    DEBUGMSGTL(("disman:expr:init", "Expression Value Table\n"));
 
44
}
 
45
 
 
46
 
 
47
netsnmp_variable_list *
 
48
expValueTable_getEntry(netsnmp_variable_list * indexes,
 
49
                       int mode, unsigned int colnum)
 
50
{
 
51
    struct expExpression  *exp;
 
52
    netsnmp_variable_list *res, *vp, *vp2;
 
53
    oid nullInstance[] = {0, 0, 0};
 
54
    int  plen;
 
55
    size_t len;
 
56
    unsigned int type = colnum-1; /* column object subIDs and type
 
57
                                      enumerations are off by one. */
 
58
 
 
59
    if (!indexes || !indexes->next_variable ||
 
60
        !indexes->next_variable->next_variable ) {
 
61
        /* XXX - Shouldn't happen! */
 
62
        return 0;
 
63
    }
 
64
 
 
65
    DEBUGMSGTL(( "disman:expr:val", "get (%d) entry (%s, %s, ", mode,
 
66
               indexes->val.string, indexes->next_variable->val.string));
 
67
    DEBUGMSGOID(("disman:expr:val",
 
68
               indexes->next_variable->next_variable->val.objid,
 
69
               indexes->next_variable->next_variable->val_len/sizeof(oid)));
 
70
    DEBUGMSG((   "disman:expr:val", ")\n"));
 
71
 
 
72
    /*
 
73
     * Locate the expression that we've been asked to evaluate
 
74
     */
 
75
    if (!indexes->val_len || !indexes->next_variable->val_len ) {
 
76
        /*
 
77
         * Incomplete expression specification
 
78
         */
 
79
        if (mode == MODE_GETNEXT || mode == MODE_GETBULK) {
 
80
            exp = expExpression_getFirstEntry();
 
81
            DEBUGMSGTL(( "disman:expr:val", "first entry (%x)\n", exp ));
 
82
        } else {
 
83
            DEBUGMSGTL(( "disman:expr:val", "incomplete request\n" ));
 
84
            return NULL;        /* No match */
 
85
        }
 
86
    } else {
 
87
        exp = expExpression_getEntry( (char*)indexes->val.string,
 
88
                                      (char*)indexes->next_variable->val.string);
 
89
        DEBUGMSGTL(( "disman:expr:val", "using entry (%x)\n", exp ));
 
90
    }
 
91
 
 
92
    /*
 
93
     * We know what type of value was requested,
 
94
     *   so ignore any non-matching expressions.
 
95
     */
 
96
    while (exp && exp->expValueType != type) {
 
97
        if (mode != MODE_GETNEXT && mode != MODE_GETBULK) {
 
98
            DEBUGMSGTL(( "disman:expr:val", "wrong type (%d != %d)\n",
 
99
                          type, (exp ? exp->expValueType : 0 )));
 
100
            return NULL;        /* Wrong type */
 
101
        }
 
102
NEXT_EXP:
 
103
        exp = expExpression_getNextEntry( exp->expOwner, exp->expName );
 
104
        DEBUGMSGTL(( "disman:expr:val", "using next entry (%x)\n", exp ));
 
105
    }
 
106
    if (!exp) {
 
107
        DEBUGMSGTL(( "disman:expr:val", "no more entries\n"));
 
108
        return NULL;    /* No match (of the required type) */
 
109
    }
 
110
 
 
111
 
 
112
    /*
 
113
     * Now consider which instance of the chosen expression is needed
 
114
     */
 
115
    vp  = indexes->next_variable->next_variable;
 
116
    if ( mode == MODE_GET ) {
 
117
        /*
 
118
         * For a GET request, check that the specified value instance
 
119
         *   is valid, and evaluate the expression using this.
 
120
         */
 
121
        if ( !vp || !vp->val_len ) {
 
122
            DEBUGMSGTL(( "disman:expr:val", "no instance index\n"));
 
123
            return NULL;  /* No instance provided */
 
124
        }
 
125
        if ( vp->val.objid[0] != 0 ) {
 
126
            DEBUGMSGTL(( "disman:expr:val",
 
127
                         "non-zero instance (%d)\n", vp->val.objid[0]));
 
128
            return NULL;  /* Invalid instance */
 
129
        }
 
130
 
 
131
        if (exp->expPrefix_len == 0 ) {
 
132
            /*
 
133
             * The only valid instance for a non-wildcarded
 
134
             *     expression is .0.0.0
 
135
             */
 
136
            if ( vp->val_len != 3*sizeof(oid) ||
 
137
                 vp->val.objid[1] != 0 ||
 
138
                 vp->val.objid[2] != 0 ) {
 
139
                DEBUGMSGTL(( "disman:expr:val", "invalid scalar instance\n"));
 
140
                return NULL;
 
141
            }
 
142
            res = expValue_evaluateExpression( exp, NULL, 0 );
 
143
            DEBUGMSGTL(( "disman:expr:val", "scalar get returned (%x)\n", res));
 
144
        } else {
 
145
            /*
 
146
             * Otherwise, skip the leading '.0' and use
 
147
             *   the remaining instance subidentifiers.
 
148
             */
 
149
            res = expValue_evaluateExpression( exp, vp->val.objid+1,
 
150
                                           vp->val_len/sizeof(oid)-1);
 
151
            DEBUGMSGTL(( "disman:expr:val", "w/card get returned (%x)\n", res));
 
152
        }
 
153
    } else {
 
154
        /*
 
155
         * For a GETNEXT request, identify the appropriate next
 
156
         *   value instance, and evaluate the expression using
 
157
         *   that, updating the index list appropriately.
 
158
         */
 
159
        if ( vp->val_len > 0 && vp->val.objid[0] != 0 ) {
 
160
            DEBUGMSGTL(( "disman:expr:val",
 
161
                         "non-zero next instance (%d)\n", vp->val.objid[0]));
 
162
            return NULL;        /* All valid instances start with .0 */
 
163
        }
 
164
        plen = exp->expPrefix_len;
 
165
        if (plen == 0 ) {
 
166
            /*
 
167
             * The only valid instances for GETNEXT on a
 
168
             *   non-wildcarded expression are .0 and .0.0
 
169
             *   Anything else is too late.
 
170
             */
 
171
            if ((vp->val_len > 2*sizeof(oid)) ||
 
172
                (vp->val_len == 2*sizeof(oid) &&
 
173
                      vp->val.objid[1] != 0)) {
 
174
                DEBUGMSGTL(( "disman:expr:val", "invalid scalar next instance\n"));
 
175
                return NULL;        /* Invalid instance */
 
176
            }
 
177
     
 
178
            /*
 
179
             * Make sure the index varbind list refers to the
 
180
             *   (only) valid instance of this expression,
 
181
             *   and evaluate it.
 
182
             */
 
183
            snmp_set_var_typed_value( indexes, ASN_OCTET_STR,
 
184
                       (u_char*)exp->expOwner, strlen(exp->expOwner));
 
185
            snmp_set_var_typed_value( indexes->next_variable, ASN_OCTET_STR,
 
186
                       (u_char*)exp->expName,  strlen(exp->expName));
 
187
            snmp_set_var_typed_value( vp, ASN_PRIV_IMPLIED_OBJECT_ID,
 
188
                       (u_char*)nullInstance, 3*sizeof(oid));
 
189
            res = expValue_evaluateExpression( exp, NULL, 0 );
 
190
            DEBUGMSGTL(( "disman:expr:val", "scalar next returned (%x)\n", res));
 
191
        } else {
 
192
            /*
 
193
             * Now comes the interesting case - finding the
 
194
             *   appropriate instance of a wildcarded expression.
 
195
             */
 
196
            if ( vp->val_len == 0 ) {
 
197
                 if ( !exp->pvars ) {
 
198
                     DEBUGMSGTL(( "disman:expr:val", "no instances\n"));
 
199
                     goto NEXT_EXP;
 
200
                 }
 
201
                 DEBUGMSGTL(( "disman:expr:val", "using first instance\n"));
 
202
                 vp2 = exp->pvars;
 
203
            } else {
 
204
                 /*
 
205
                  * Search the list of instances for the (first) greater one
 
206
                  *   XXX - This comparison relies on the OID of the prefix
 
207
                  *         object being the same length as the wildcarded
 
208
                  *         parameter objects.  It ain't necessarily so.
 
209
                  */
 
210
                 for ( vp2 = exp->pvars; vp2; vp2->next_variable ) {
 
211
                     if ( snmp_oid_compare( vp2->name        + plen,
 
212
                                            vp2->name_length - plen,
 
213
                                            vp->name,
 
214
                                            vp->name_length) < 0 ) {
 
215
                         DEBUGMSGTL(( "disman:expr:val", "next instance "));
 
216
                         DEBUGMSGOID(("disman:expr:val",  vp2->name, vp2->name_length ));
 
217
                         DEBUGMSG((   "disman:expr:val", "\n"));
 
218
                         break;
 
219
                     }
 
220
                 }
 
221
                 if (!vp2) {
 
222
                     DEBUGMSGTL(( "disman:expr:val", "no next instance\n"));
 
223
                     goto NEXT_EXP;
 
224
                 }
 
225
            }
 
226
            snmp_set_var_typed_value( indexes, ASN_OCTET_STR,
 
227
                       (u_char*)exp->expOwner, strlen(exp->expOwner));
 
228
            snmp_set_var_typed_value( indexes->next_variable, ASN_OCTET_STR,
 
229
                       (u_char*)exp->expName,  strlen(exp->expName));
 
230
            if (vp2) {
 
231
                len = vp2->name_length - exp->expPrefix_len;
 
232
                snmp_set_var_typed_value( vp, ASN_PRIV_IMPLIED_OBJECT_ID,
 
233
                      (u_char*)(vp2->name+exp->expPrefix_len), len);
 
234
            }
 
235
            res = expValue_evaluateExpression( exp, vp->val.objid+1, len-1);
 
236
            DEBUGMSGTL(( "disman:expr:val", "w/card next returned (%x)\n", res));
 
237
        }
 
238
    }
 
239
    return res;
 
240
}
 
241
 
 
242
/** handles requests for the expValueTable table */
 
243
int
 
244
expValueTable_handler(netsnmp_mib_handler *handler,
 
245
                      netsnmp_handler_registration *reginfo,
 
246
                      netsnmp_agent_request_info *reqinfo,
 
247
                      netsnmp_request_info *requests)
 
248
{
 
249
 
 
250
    netsnmp_request_info       *request;
 
251
    netsnmp_table_request_info *tinfo;
 
252
    netsnmp_variable_list      *value;
 
253
    oid    expValueOID[] = { 1, 3, 6, 1, 2, 1, 90, 1, 3, 1, 1, 99 };
 
254
    size_t expValueOID_len = OID_LENGTH(expValueOID);
 
255
    oid    name_buf[ MAX_OID_LEN ];
 
256
    oid   *name_ptr = name_buf;
 
257
    size_t name_buf_len = MAX_OID_LEN;
 
258
 
 
259
    DEBUGMSGTL(("disman:expr:mib", "Expression Value Table handler (%d)\n",
 
260
                                    reqinfo->mode));
 
261
    switch (reqinfo->mode) {
 
262
    case MODE_GET:
 
263
    case MODE_GETNEXT:
 
264
        for (request = requests; request; request = request->next) {
 
265
            tinfo = netsnmp_extract_table_info(request);
 
266
            value = expValueTable_getEntry(tinfo->indexes,
 
267
                                           reqinfo->mode,
 
268
                                           tinfo->colnum);
 
269
            if (!value || !value->val.integer) {
 
270
                netsnmp_set_request_error(reqinfo, request,
 
271
                                         (reqinfo->mode == MODE_GET) ? 
 
272
                                                 SNMP_NOSUCHINSTANCE :
 
273
                                                 SNMP_ENDOFMIBVIEW);
 
274
                continue;
 
275
            }
 
276
            if ( reqinfo->mode == MODE_GETNEXT ) {
 
277
                 /*
 
278
                  * Need to update the request varbind OID
 
279
                  *   to match the instance just evaluated.
 
280
                  * (XXX - Is this the appropriate mechanism?)
 
281
                  */
 
282
                build_oid_noalloc( name_buf, MAX_OID_LEN, &name_buf_len,
 
283
                           expValueOID, expValueOID_len, tinfo->indexes );
 
284
                name_buf[ expValueOID_len -1 ] = tinfo->colnum;
 
285
                snmp_set_var_objid(request->requestvb, name_buf, name_buf_len);
 
286
            }
 
287
 
 
288
            switch (tinfo->colnum) {
 
289
            case COLUMN_EXPVALUECOUNTER32VAL:
 
290
                snmp_set_var_typed_integer(request->requestvb, ASN_COUNTER,
 
291
                                          *value->val.integer);
 
292
                break;
 
293
            case COLUMN_EXPVALUEUNSIGNED32VAL:
 
294
                snmp_set_var_typed_integer(request->requestvb, ASN_UNSIGNED,
 
295
                                          *value->val.integer);
 
296
                break;
 
297
            case COLUMN_EXPVALUETIMETICKSVAL:
 
298
                snmp_set_var_typed_integer(request->requestvb, ASN_TIMETICKS,
 
299
                                          *value->val.integer);
 
300
                break;
 
301
            case COLUMN_EXPVALUEINTEGER32VAL:
 
302
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
 
303
                                          *value->val.integer);
 
304
                break;
 
305
            case COLUMN_EXPVALUEIPADDRESSVAL:
 
306
                snmp_set_var_typed_integer(request->requestvb, ASN_IPADDRESS,
 
307
                                          *value->val.integer);
 
308
                break;
 
309
            case COLUMN_EXPVALUEOCTETSTRINGVAL:
 
310
                snmp_set_var_typed_value(  request->requestvb, ASN_OCTET_STR,
 
311
                                           value->val.string,  value->val_len);
 
312
                break;
 
313
            case COLUMN_EXPVALUEOIDVAL:
 
314
                snmp_set_var_typed_value(  request->requestvb, ASN_OBJECT_ID,
 
315
                                   (u_char *)value->val.objid, value->val_len);
 
316
                break;
 
317
            case COLUMN_EXPVALUECOUNTER64VAL:
 
318
                snmp_set_var_typed_value(  request->requestvb, ASN_COUNTER64,
 
319
                               (u_char *)value->val.counter64, value->val_len);
 
320
                break;
 
321
            }
 
322
        }
 
323
        break;
 
324
 
 
325
    }
 
326
    DEBUGMSGTL(("disman:expr:mib", "Expression Value handler - done \n"));
 
327
    return SNMP_ERR_NOERROR;
 
328
}