~ubuntu-branches/ubuntu/gutsy/net-snmp/gutsy-security

« back to all changes in this revision

Viewing changes to agent/mibgroup/header_complex.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
/*
 
2
 * header complex:  More complex storage and data sorting for mib modules 
 
3
 */
 
4
 
 
5
#include <net-snmp/net-snmp-config.h>
 
6
 
 
7
#include <sys/types.h>
 
8
#if HAVE_WINSOCK_H
 
9
#include <winsock.h>
 
10
#endif
 
11
#if HAVE_STDLIB_H
 
12
#include <stdlib.h>
 
13
#endif
 
14
#if HAVE_STRING_H
 
15
#include <string.h>
 
16
#else
 
17
#include <strings.h>
 
18
#endif
 
19
 
 
20
#include <net-snmp/net-snmp-includes.h>
 
21
#include <net-snmp/agent/net-snmp-agent-includes.h>
 
22
#include "header_complex.h"
 
23
 
 
24
int
 
25
header_complex_generate_varoid(netsnmp_variable_list * var)
 
26
{
 
27
    int             i;
 
28
 
 
29
    if (var->name == NULL) {
 
30
        /*
 
31
         * assume cached value is correct 
 
32
         */
 
33
        switch (var->type) {
 
34
        case ASN_INTEGER:
 
35
        case ASN_COUNTER:
 
36
        case ASN_GAUGE:
 
37
        case ASN_TIMETICKS:
 
38
            var->name_length = 1;
 
39
            var->name = (oid *) malloc(sizeof(oid));
 
40
            if (var->name == NULL)
 
41
                return SNMPERR_GENERR;
 
42
            var->name[0] = *(var->val.integer);
 
43
            break;
 
44
 
 
45
        case ASN_PRIV_IMPLIED_OBJECT_ID:
 
46
            var->name_length = var->val_len / sizeof(oid);
 
47
            var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
 
48
            if (var->name == NULL)
 
49
                return SNMPERR_GENERR;
 
50
 
 
51
            for (i = 0; i < (int) var->name_length; i++)
 
52
                var->name[i] = var->val.objid[i];
 
53
            break;
 
54
 
 
55
        case ASN_OBJECT_ID:
 
56
            var->name_length = var->val_len / sizeof(oid) + 1;
 
57
            var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
 
58
            if (var->name == NULL)
 
59
                return SNMPERR_GENERR;
 
60
 
 
61
            var->name[0] = var->name_length - 1;
 
62
            for (i = 0; i < (int) var->name_length - 1; i++)
 
63
                var->name[i + 1] = var->val.objid[i];
 
64
            break;
 
65
 
 
66
        case ASN_PRIV_IMPLIED_OCTET_STR:
 
67
            var->name_length = var->val_len;
 
68
            var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
 
69
            if (var->name == NULL)
 
70
                return SNMPERR_GENERR;
 
71
 
 
72
            for (i = 0; i < (int) var->val_len; i++)
 
73
                var->name[i] = (oid) var->val.string[i];
 
74
            break;
 
75
 
 
76
        case ASN_OPAQUE:
 
77
        case ASN_OCTET_STR:
 
78
            var->name_length = var->val_len + 1;
 
79
            var->name = (oid *) malloc(sizeof(oid) * (var->name_length));
 
80
            if (var->name == NULL)
 
81
                return SNMPERR_GENERR;
 
82
 
 
83
            var->name[0] = (oid) var->val_len;
 
84
            for (i = 0; i < (int) var->val_len; i++)
 
85
                var->name[i + 1] = (oid) var->val.string[i];
 
86
            break;
 
87
 
 
88
        default:
 
89
            DEBUGMSGTL(("header_complex_generate_varoid",
 
90
                        "invalid asn type: %d\n", var->type));
 
91
            return SNMPERR_GENERR;
 
92
        }
 
93
    }
 
94
    if (var->name_length > MAX_OID_LEN) {
 
95
        DEBUGMSGTL(("header_complex_generate_varoid",
 
96
                    "Something terribly wrong, namelen = %d\n",
 
97
                    var->name_length));
 
98
        return SNMPERR_GENERR;
 
99
    }
 
100
 
 
101
    return SNMPERR_SUCCESS;
 
102
}
 
103
 
 
104
/*
 
105
 * header_complex_parse_oid(): parses an index to the usmTable to
 
106
 * break it down into a engineID component and a name component.
 
107
 * The results are stored in the data pointer, as a varbindlist:
 
108
 * 
 
109
 * 
 
110
 * returns 1 if an error is encountered, or 0 if successful.
 
111
 */
 
112
int
 
113
header_complex_parse_oid(oid * oidIndex, size_t oidLen,
 
114
                         netsnmp_variable_list * data)
 
115
{
 
116
    netsnmp_variable_list *var = data;
 
117
    int             i, itmp;
 
118
 
 
119
    while (var && oidLen > 0) {
 
120
        switch (var->type) {
 
121
        case ASN_INTEGER:
 
122
        case ASN_COUNTER:
 
123
        case ASN_GAUGE:
 
124
        case ASN_TIMETICKS:
 
125
            var->val.integer = (long *) calloc(1, sizeof(long));
 
126
            if (var->val.string == NULL)
 
127
                return SNMPERR_GENERR;
 
128
 
 
129
            *var->val.integer = (long) *oidIndex++;
 
130
            var->val_len = sizeof(long);
 
131
            oidLen--;
 
132
            DEBUGMSGTL(("header_complex_parse_oid",
 
133
                        "Parsed int(%d): %d\n", var->type,
 
134
                        *var->val.integer));
 
135
            break;
 
136
 
 
137
        case ASN_OBJECT_ID:
 
138
        case ASN_PRIV_IMPLIED_OBJECT_ID:
 
139
            if (var->type == ASN_PRIV_IMPLIED_OBJECT_ID) {
 
140
                itmp = oidLen;
 
141
            } else {
 
142
                itmp = (long) *oidIndex++;
 
143
                oidLen--;
 
144
                if (itmp > (int) oidLen)
 
145
                    return SNMPERR_GENERR;
 
146
            }
 
147
 
 
148
            if (itmp == 0)
 
149
                break;          /* zero length strings shouldn't malloc */
 
150
 
 
151
            var->val_len = itmp * sizeof(oid);
 
152
            var->val.objid = (oid *) calloc(1, var->val_len);
 
153
            if (var->val.objid == NULL)
 
154
                return SNMPERR_GENERR;
 
155
 
 
156
            for (i = 0; i < itmp; i++)
 
157
                var->val.objid[i] = (u_char) * oidIndex++;
 
158
            oidLen -= itmp;
 
159
 
 
160
            DEBUGMSGTL(("header_complex_parse_oid", "Parsed oid: "));
 
161
            DEBUGMSGOID(("header_complex_parse_oid", var->val.objid,
 
162
                         var->val_len / sizeof(oid)));
 
163
            DEBUGMSG(("header_complex_parse_oid", "\n"));
 
164
            break;
 
165
 
 
166
        case ASN_OPAQUE:
 
167
        case ASN_OCTET_STR:
 
168
        case ASN_PRIV_IMPLIED_OCTET_STR:
 
169
            if (var->type == ASN_PRIV_IMPLIED_OCTET_STR) {
 
170
                itmp = oidLen;
 
171
            } else {
 
172
                itmp = (long) *oidIndex++;
 
173
                oidLen--;
 
174
                if (itmp > (int) oidLen)
 
175
                    return SNMPERR_GENERR;
 
176
            }
 
177
 
 
178
            if (itmp == 0)
 
179
                break;          /* zero length strings shouldn't malloc */
 
180
 
 
181
            /*
 
182
             * malloc by size+1 to allow a null to be appended. 
 
183
             */
 
184
            var->val_len = itmp;
 
185
            var->val.string = (u_char *) calloc(1, itmp + 1);
 
186
            if (var->val.string == NULL)
 
187
                return SNMPERR_GENERR;
 
188
 
 
189
            for (i = 0; i < itmp; i++)
 
190
                var->val.string[i] = (u_char) * oidIndex++;
 
191
            var->val.string[itmp] = '\0';
 
192
            oidLen -= itmp;
 
193
 
 
194
            DEBUGMSGTL(("header_complex_parse_oid",
 
195
                        "Parsed str(%d): %s\n", var->type,
 
196
                        var->val.string));
 
197
            break;
 
198
 
 
199
        default:
 
200
            DEBUGMSGTL(("header_complex_parse_oid",
 
201
                        "invalid asn type: %d\n", var->type));
 
202
            return SNMPERR_GENERR;
 
203
        }
 
204
        var = var->next_variable;
 
205
    }
 
206
    if (var != NULL || oidLen > 0)
 
207
        return SNMPERR_GENERR;
 
208
    return SNMPERR_SUCCESS;
 
209
}
 
210
 
 
211
 
 
212
void
 
213
header_complex_generate_oid(oid * name, /* out */
 
214
                            size_t * length,    /* out */
 
215
                            oid * prefix,
 
216
                            size_t prefix_len,
 
217
                            netsnmp_variable_list * data)
 
218
{
 
219
 
 
220
    oid            *oidptr;
 
221
    netsnmp_variable_list *var;
 
222
 
 
223
    if (prefix) {
 
224
        memcpy(name, prefix, prefix_len * sizeof(oid));
 
225
        oidptr = (name + (prefix_len));
 
226
        *length = prefix_len;
 
227
    } else {
 
228
        oidptr = name;
 
229
        *length = 0;
 
230
    }
 
231
 
 
232
    for (var = data; var != NULL; var = var->next_variable) {
 
233
        header_complex_generate_varoid(var);
 
234
        memcpy(oidptr, var->name, sizeof(oid) * var->name_length);
 
235
        oidptr = oidptr + var->name_length;
 
236
        *length += var->name_length;
 
237
    }
 
238
 
 
239
    DEBUGMSGTL(("header_complex_generate_oid", "generated: "));
 
240
    DEBUGMSGOID(("header_complex_generate_oid", name, *length));
 
241
    DEBUGMSG(("header_complex_generate_oid", "\n"));
 
242
}
 
243
 
 
244
/*
 
245
 * finds the data in "datalist" stored at "index" 
 
246
 */
 
247
void           *
 
248
header_complex_get(struct header_complex_index *datalist,
 
249
                   netsnmp_variable_list * index)
 
250
{
 
251
    oid             searchfor[MAX_OID_LEN];
 
252
    size_t          searchfor_len;
 
253
 
 
254
    header_complex_generate_oid(searchfor,      /* out */
 
255
                                &searchfor_len, /* out */
 
256
                                NULL, 0, index);
 
257
    return header_complex_get_from_oid(datalist, searchfor, searchfor_len);
 
258
}
 
259
 
 
260
void           *
 
261
header_complex_get_from_oid(struct header_complex_index *datalist,
 
262
                            oid * searchfor, size_t searchfor_len)
 
263
{
 
264
    struct header_complex_index *nptr;
 
265
    for (nptr = datalist; nptr != NULL; nptr = nptr->next) {
 
266
        if (netsnmp_oid_equals(searchfor, searchfor_len,
 
267
                             nptr->name, nptr->namelen) == 0)
 
268
            return nptr->data;
 
269
    }
 
270
    return NULL;
 
271
}
 
272
 
 
273
 
 
274
void           *
 
275
header_complex(struct header_complex_index *datalist,
 
276
               struct variable *vp,
 
277
               oid * name,
 
278
               size_t * length,
 
279
               int exact, size_t * var_len, WriteMethod ** write_method)
 
280
{
 
281
 
 
282
    struct header_complex_index *nptr, *found = NULL;
 
283
    oid             indexOid[MAX_OID_LEN];
 
284
    size_t          len;
 
285
    int             result;
 
286
 
 
287
    /*
 
288
     * set up some nice defaults for the user 
 
289
     */
 
290
    if (write_method)
 
291
        *write_method = NULL;
 
292
    if (var_len)
 
293
        *var_len = sizeof(long);
 
294
 
 
295
    for (nptr = datalist; nptr != NULL && found == NULL; nptr = nptr->next) {
 
296
        if (vp) {
 
297
            memcpy(indexOid, vp->name, vp->namelen * sizeof(oid));
 
298
            memcpy(indexOid + vp->namelen, nptr->name,
 
299
                   nptr->namelen * sizeof(oid));
 
300
            len = vp->namelen + nptr->namelen;
 
301
        } else {
 
302
            memcpy(indexOid, nptr->name, nptr->namelen * sizeof(oid));
 
303
            len = nptr->namelen;
 
304
        }
 
305
        result = snmp_oid_compare(name, *length, indexOid, len);
 
306
        DEBUGMSGTL(("header_complex", "Checking: "));
 
307
        DEBUGMSGOID(("header_complex", indexOid, len));
 
308
        DEBUGMSG(("header_complex", "\n"));
 
309
 
 
310
        if (exact) {
 
311
            if (result == 0) {
 
312
                found = nptr;
 
313
            }
 
314
        } else {
 
315
            if (result == 0) {
 
316
                /*
 
317
                 * found an exact match.  Need the next one for !exact 
 
318
                 */
 
319
                if (nptr->next)
 
320
                    found = nptr->next;
 
321
            } else if (result == -1) {
 
322
                found = nptr;
 
323
            }
 
324
        }
 
325
    }
 
326
    if (found) {
 
327
        if (vp) {
 
328
            memcpy(name, vp->name, vp->namelen * sizeof(oid));
 
329
            memcpy(name + vp->namelen, found->name,
 
330
                   found->namelen * sizeof(oid));
 
331
            *length = vp->namelen + found->namelen;
 
332
        } else {
 
333
            memcpy(name, found->name, found->namelen * sizeof(oid));
 
334
            *length = found->namelen;
 
335
        }
 
336
        return found->data;
 
337
    }
 
338
 
 
339
    return NULL;
 
340
}
 
341
 
 
342
struct header_complex_index *
 
343
header_complex_add_data(struct header_complex_index **thedata,
 
344
                        netsnmp_variable_list * var, void *data)
 
345
{
 
346
    oid             newoid[MAX_OID_LEN];
 
347
    size_t          newoid_len;
 
348
    struct header_complex_index *ret;
 
349
 
 
350
    if (thedata == NULL || var == NULL || data == NULL)
 
351
        return NULL;
 
352
 
 
353
    header_complex_generate_oid(newoid, &newoid_len, NULL, 0, var);
 
354
    ret =
 
355
        header_complex_add_data_by_oid(thedata, newoid, newoid_len, data);
 
356
    /*
 
357
     * free the variable list, but not the enclosed data!  it's not ours! 
 
358
     */
 
359
    snmp_free_varbind(var);
 
360
    return (ret);
 
361
}
 
362
 
 
363
struct header_complex_index *
 
364
header_complex_add_data_by_oid(struct header_complex_index **thedata,
 
365
                               oid * newoid, size_t newoid_len, void *data)
 
366
{
 
367
    struct header_complex_index *hciptrn, *hciptrp, *ourself;
 
368
 
 
369
    if (thedata == NULL || newoid == NULL || data == NULL)
 
370
        return NULL;
 
371
 
 
372
    for (hciptrn = *thedata, hciptrp = NULL;
 
373
         hciptrn != NULL; hciptrp = hciptrn, hciptrn = hciptrn->next)
 
374
        /*
 
375
         * XXX: check for == and error (overlapping table entries) 
 
376
         */
 
377
        if (snmp_oid_compare
 
378
            (hciptrn->name, hciptrn->namelen, newoid, newoid_len)
 
379
            > 0)
 
380
            break;
 
381
 
 
382
    /*
 
383
     * nptr should now point to the spot that we need to add ourselves
 
384
     * in front of, and pptr should be our new 'prev'. 
 
385
     */
 
386
 
 
387
    /*
 
388
     * create ourselves 
 
389
     */
 
390
    ourself = (struct header_complex_index *)
 
391
        SNMP_MALLOC_STRUCT(header_complex_index);
 
392
 
 
393
    /*
 
394
     * change our pointers 
 
395
     */
 
396
    ourself->prev = hciptrp;
 
397
    ourself->next = hciptrn;
 
398
 
 
399
    if (ourself->next)
 
400
        ourself->next->prev = ourself;
 
401
 
 
402
    if (ourself->prev)
 
403
        ourself->prev->next = ourself;
 
404
 
 
405
    ourself->data = data;
 
406
    ourself->name = snmp_duplicate_objid(newoid, newoid_len);
 
407
    ourself->namelen = newoid_len;
 
408
 
 
409
    /*
 
410
     * rewind to the head of the list and return it (since the new head
 
411
     * could be us, we need to notify the above routine who the head now is. 
 
412
     */
 
413
    for (hciptrp = ourself; hciptrp->prev != NULL;
 
414
         hciptrp = hciptrp->prev);
 
415
 
 
416
    *thedata = hciptrp;
 
417
    DEBUGMSGTL(("header_complex_add_data", "adding something...\n"));
 
418
 
 
419
    return hciptrp;
 
420
}
 
421
 
 
422
/*
 
423
 * extracts an entry from the storage space (removing it from future
 
424
 * accesses) and returns the data stored there
 
425
 * 
 
426
 * Modifies "thetop" pointer as needed (and if present) if were
 
427
 * extracting the first node.
 
428
 */
 
429
 
 
430
void           *
 
431
header_complex_extract_entry(struct header_complex_index **thetop,
 
432
                             struct header_complex_index *thespot)
 
433
{
 
434
    struct header_complex_index *hciptrp, *hciptrn;
 
435
    void           *retdata = thespot->data;
 
436
 
 
437
    if (thespot == NULL) {
 
438
        DEBUGMSGTL(("header_complex_extract_entry",
 
439
                    "Null pointer asked to be extracted\n"));
 
440
        return NULL;
 
441
    }
 
442
 
 
443
    hciptrp = thespot->prev;
 
444
    hciptrn = thespot->next;
 
445
 
 
446
    if (hciptrp)
 
447
        hciptrp->next = hciptrn;
 
448
    else if (thetop)
 
449
        *thetop = hciptrn;
 
450
 
 
451
    if (hciptrn)
 
452
        hciptrn->prev = hciptrp;
 
453
 
 
454
    if (thespot->name)
 
455
        free(thespot->name);
 
456
 
 
457
    free(thespot);
 
458
    return retdata;
 
459
}
 
460
 
 
461
/*
 
462
 * wipe out a single entry 
 
463
 */
 
464
void
 
465
header_complex_free_entry(struct header_complex_index *theentry,
 
466
                          HeaderComplexCleaner * cleaner)
 
467
{
 
468
    void           *data;
 
469
    data = header_complex_extract_entry(NULL, theentry);
 
470
    (*cleaner) (data);
 
471
}
 
472
 
 
473
/*
 
474
 * completely wipe out all entries in our data store 
 
475
 */
 
476
void
 
477
header_complex_free_all(struct header_complex_index *thestuff,
 
478
                        HeaderComplexCleaner * cleaner)
 
479
{
 
480
    struct header_complex_index *hciptr, *hciptrn;
 
481
 
 
482
    for (hciptr = thestuff; hciptr != NULL; hciptr = hciptrn) {
 
483
        hciptrn = hciptr->next; /* need to extract this before deleting it */
 
484
        header_complex_free_entry(hciptr, cleaner);
 
485
    }
 
486
}
 
487
 
 
488
struct header_complex_index *
 
489
header_complex_find_entry(struct header_complex_index *thestuff,
 
490
                          void *theentry)
 
491
{
 
492
    struct header_complex_index *hciptr;
 
493
 
 
494
    for (hciptr = thestuff; hciptr != NULL && hciptr->data != theentry;
 
495
         hciptr = hciptr->next);
 
496
    return hciptr;
 
497
}
 
498
 
 
499
#ifdef TESTING
 
500
 
 
501
void
 
502
header_complex_dump(struct header_complex_index *thestuff)
 
503
{
 
504
    struct header_complex_index *hciptr;
 
505
    oid             oidsave[MAX_OID_LEN];
 
506
    size_t          len;
 
507
 
 
508
    for (hciptr = thestuff; hciptr != NULL; hciptr = hciptr->next) {
 
509
        DEBUGMSGTL(("header_complex_dump", "var:  "));
 
510
        header_complex_generate_oid(oidsave, &len, NULL, 0, hciptr->);
 
511
        DEBUGMSGOID(("header_complex_dump", oidsave, len));
 
512
        DEBUGMSG(("header_complex_dump", "\n"));
 
513
    }
 
514
}
 
515
 
 
516
main()
 
517
{
 
518
    oid             oidsave[MAX_OID_LEN];
 
519
    int             len = MAX_OID_LEN, len2;
 
520
    netsnmp_variable_list *vars;
 
521
    long            ltmp = 4242, ltmp2 = 88, ltmp3 = 1, ltmp4 = 4200;
 
522
    oid             ourprefix[] = { 1, 2, 3, 4 };
 
523
    oid             testparse[] = { 4, 116, 101, 115, 116, 4200 };
 
524
    int             ret;
 
525
 
 
526
    char           *string = "wes", *string2 = "dawn", *string3 = "test";
 
527
 
 
528
    struct header_complex_index *thestorage = NULL;
 
529
 
 
530
    debug_register_tokens("header_complex");
 
531
    snmp_set_do_debugging(1);
 
532
 
 
533
    vars = NULL;
 
534
    len2 = sizeof(ltmp);
 
535
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp,
 
536
                              len2);
 
537
    header_complex_add_data(&thestorage, vars, ourprefix);
 
538
 
 
539
    vars = NULL;
 
540
    len2 = strlen(string);
 
541
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string, len2);
 
542
    header_complex_add_data(&thestorage, vars, ourprefix);
 
543
 
 
544
    vars = NULL;
 
545
    len2 = sizeof(ltmp2);
 
546
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp2,
 
547
                              len2);
 
548
    header_complex_add_data(&thestorage, vars, ourprefix);
 
549
 
 
550
    vars = NULL;
 
551
    len2 = strlen(string2);
 
552
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string2,
 
553
                              len2);
 
554
    header_complex_add_data(&thestorage, vars, ourprefix);
 
555
 
 
556
    vars = NULL;
 
557
    len2 = sizeof(ltmp3);
 
558
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp3,
 
559
                              len2);
 
560
    header_complex_add_data(&thestorage, vars, ourprefix);
 
561
 
 
562
    vars = NULL;
 
563
    len2 = strlen(string3);
 
564
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string3,
 
565
                              len2);
 
566
    len2 = sizeof(ltmp4);
 
567
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) &ltmp4,
 
568
                              len2);
 
569
    header_complex_add_data(&thestorage, vars, ourprefix);
 
570
 
 
571
    header_complex_dump(thestorage);
 
572
 
 
573
    vars = NULL;
 
574
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, NULL, 0);
 
575
    snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, NULL, 0);
 
576
    ret =
 
577
        header_complex_parse_oid(testparse,
 
578
                                 sizeof(testparse) / sizeof(oid), vars);
 
579
    DEBUGMSGTL(("header_complex_test", "parse returned %d...\n", ret));
 
580
 
 
581
}
 
582
#endif