2
* header complex: More complex storage and data sorting for mib modules
5
#include <net-snmp/net-snmp-config.h>
20
#include <net-snmp/net-snmp-includes.h>
21
#include <net-snmp/agent/net-snmp-agent-includes.h>
22
#include "header_complex.h"
25
header_complex_generate_varoid(netsnmp_variable_list * var)
29
if (var->name == NULL) {
31
* assume cached value is correct
39
var->name = (oid *) malloc(sizeof(oid));
40
if (var->name == NULL)
41
return SNMPERR_GENERR;
42
var->name[0] = *(var->val.integer);
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;
51
for (i = 0; i < (int) var->name_length; i++)
52
var->name[i] = var->val.objid[i];
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;
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];
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;
72
for (i = 0; i < (int) var->val_len; i++)
73
var->name[i] = (oid) var->val.string[i];
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;
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];
89
DEBUGMSGTL(("header_complex_generate_varoid",
90
"invalid asn type: %d\n", var->type));
91
return SNMPERR_GENERR;
94
if (var->name_length > MAX_OID_LEN) {
95
DEBUGMSGTL(("header_complex_generate_varoid",
96
"Something terribly wrong, namelen = %d\n",
98
return SNMPERR_GENERR;
101
return SNMPERR_SUCCESS;
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:
110
* returns 1 if an error is encountered, or 0 if successful.
113
header_complex_parse_oid(oid * oidIndex, size_t oidLen,
114
netsnmp_variable_list * data)
116
netsnmp_variable_list *var = data;
119
while (var && oidLen > 0) {
125
var->val.integer = (long *) calloc(1, sizeof(long));
126
if (var->val.string == NULL)
127
return SNMPERR_GENERR;
129
*var->val.integer = (long) *oidIndex++;
130
var->val_len = sizeof(long);
132
DEBUGMSGTL(("header_complex_parse_oid",
133
"Parsed int(%d): %d\n", var->type,
138
case ASN_PRIV_IMPLIED_OBJECT_ID:
139
if (var->type == ASN_PRIV_IMPLIED_OBJECT_ID) {
142
itmp = (long) *oidIndex++;
144
if (itmp > (int) oidLen)
145
return SNMPERR_GENERR;
149
break; /* zero length strings shouldn't malloc */
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;
156
for (i = 0; i < itmp; i++)
157
var->val.objid[i] = (u_char) * oidIndex++;
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"));
168
case ASN_PRIV_IMPLIED_OCTET_STR:
169
if (var->type == ASN_PRIV_IMPLIED_OCTET_STR) {
172
itmp = (long) *oidIndex++;
174
if (itmp > (int) oidLen)
175
return SNMPERR_GENERR;
179
break; /* zero length strings shouldn't malloc */
182
* malloc by size+1 to allow a null to be appended.
185
var->val.string = (u_char *) calloc(1, itmp + 1);
186
if (var->val.string == NULL)
187
return SNMPERR_GENERR;
189
for (i = 0; i < itmp; i++)
190
var->val.string[i] = (u_char) * oidIndex++;
191
var->val.string[itmp] = '\0';
194
DEBUGMSGTL(("header_complex_parse_oid",
195
"Parsed str(%d): %s\n", var->type,
200
DEBUGMSGTL(("header_complex_parse_oid",
201
"invalid asn type: %d\n", var->type));
202
return SNMPERR_GENERR;
204
var = var->next_variable;
206
if (var != NULL || oidLen > 0)
207
return SNMPERR_GENERR;
208
return SNMPERR_SUCCESS;
213
header_complex_generate_oid(oid * name, /* out */
214
size_t * length, /* out */
217
netsnmp_variable_list * data)
221
netsnmp_variable_list *var;
224
memcpy(name, prefix, prefix_len * sizeof(oid));
225
oidptr = (name + (prefix_len));
226
*length = prefix_len;
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;
239
DEBUGMSGTL(("header_complex_generate_oid", "generated: "));
240
DEBUGMSGOID(("header_complex_generate_oid", name, *length));
241
DEBUGMSG(("header_complex_generate_oid", "\n"));
245
* finds the data in "datalist" stored at "index"
248
header_complex_get(struct header_complex_index *datalist,
249
netsnmp_variable_list * index)
251
oid searchfor[MAX_OID_LEN];
252
size_t searchfor_len;
254
header_complex_generate_oid(searchfor, /* out */
255
&searchfor_len, /* out */
257
return header_complex_get_from_oid(datalist, searchfor, searchfor_len);
261
header_complex_get_from_oid(struct header_complex_index *datalist,
262
oid * searchfor, size_t searchfor_len)
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)
275
header_complex(struct header_complex_index *datalist,
279
int exact, size_t * var_len, WriteMethod ** write_method)
282
struct header_complex_index *nptr, *found = NULL;
283
oid indexOid[MAX_OID_LEN];
288
* set up some nice defaults for the user
291
*write_method = NULL;
293
*var_len = sizeof(long);
295
for (nptr = datalist; nptr != NULL && found == NULL; nptr = nptr->next) {
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;
302
memcpy(indexOid, nptr->name, nptr->namelen * sizeof(oid));
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"));
317
* found an exact match. Need the next one for !exact
321
} else if (result == -1) {
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;
333
memcpy(name, found->name, found->namelen * sizeof(oid));
334
*length = found->namelen;
342
struct header_complex_index *
343
header_complex_add_data(struct header_complex_index **thedata,
344
netsnmp_variable_list * var, void *data)
346
oid newoid[MAX_OID_LEN];
348
struct header_complex_index *ret;
350
if (thedata == NULL || var == NULL || data == NULL)
353
header_complex_generate_oid(newoid, &newoid_len, NULL, 0, var);
355
header_complex_add_data_by_oid(thedata, newoid, newoid_len, data);
357
* free the variable list, but not the enclosed data! it's not ours!
359
snmp_free_varbind(var);
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)
367
struct header_complex_index *hciptrn, *hciptrp, *ourself;
369
if (thedata == NULL || newoid == NULL || data == NULL)
372
for (hciptrn = *thedata, hciptrp = NULL;
373
hciptrn != NULL; hciptrp = hciptrn, hciptrn = hciptrn->next)
375
* XXX: check for == and error (overlapping table entries)
378
(hciptrn->name, hciptrn->namelen, newoid, newoid_len)
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'.
390
ourself = (struct header_complex_index *)
391
SNMP_MALLOC_STRUCT(header_complex_index);
394
* change our pointers
396
ourself->prev = hciptrp;
397
ourself->next = hciptrn;
400
ourself->next->prev = ourself;
403
ourself->prev->next = ourself;
405
ourself->data = data;
406
ourself->name = snmp_duplicate_objid(newoid, newoid_len);
407
ourself->namelen = newoid_len;
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.
413
for (hciptrp = ourself; hciptrp->prev != NULL;
414
hciptrp = hciptrp->prev);
417
DEBUGMSGTL(("header_complex_add_data", "adding something...\n"));
423
* extracts an entry from the storage space (removing it from future
424
* accesses) and returns the data stored there
426
* Modifies "thetop" pointer as needed (and if present) if were
427
* extracting the first node.
431
header_complex_extract_entry(struct header_complex_index **thetop,
432
struct header_complex_index *thespot)
434
struct header_complex_index *hciptrp, *hciptrn;
435
void *retdata = thespot->data;
437
if (thespot == NULL) {
438
DEBUGMSGTL(("header_complex_extract_entry",
439
"Null pointer asked to be extracted\n"));
443
hciptrp = thespot->prev;
444
hciptrn = thespot->next;
447
hciptrp->next = hciptrn;
452
hciptrn->prev = hciptrp;
462
* wipe out a single entry
465
header_complex_free_entry(struct header_complex_index *theentry,
466
HeaderComplexCleaner * cleaner)
469
data = header_complex_extract_entry(NULL, theentry);
474
* completely wipe out all entries in our data store
477
header_complex_free_all(struct header_complex_index *thestuff,
478
HeaderComplexCleaner * cleaner)
480
struct header_complex_index *hciptr, *hciptrn;
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);
488
struct header_complex_index *
489
header_complex_find_entry(struct header_complex_index *thestuff,
492
struct header_complex_index *hciptr;
494
for (hciptr = thestuff; hciptr != NULL && hciptr->data != theentry;
495
hciptr = hciptr->next);
502
header_complex_dump(struct header_complex_index *thestuff)
504
struct header_complex_index *hciptr;
505
oid oidsave[MAX_OID_LEN];
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"));
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 };
526
char *string = "wes", *string2 = "dawn", *string3 = "test";
528
struct header_complex_index *thestorage = NULL;
530
debug_register_tokens("header_complex");
531
snmp_set_do_debugging(1);
535
snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) <mp,
537
header_complex_add_data(&thestorage, vars, ourprefix);
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);
545
len2 = sizeof(ltmp2);
546
snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) <mp2,
548
header_complex_add_data(&thestorage, vars, ourprefix);
551
len2 = strlen(string2);
552
snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string2,
554
header_complex_add_data(&thestorage, vars, ourprefix);
557
len2 = sizeof(ltmp3);
558
snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) <mp3,
560
header_complex_add_data(&thestorage, vars, ourprefix);
563
len2 = strlen(string3);
564
snmp_varlist_add_variable(&vars, NULL, 0, ASN_OCTET_STR, string3,
566
len2 = sizeof(ltmp4);
567
snmp_varlist_add_variable(&vars, NULL, 0, ASN_INTEGER, (char *) <mp4,
569
header_complex_add_data(&thestorage, vars, ourprefix);
571
header_complex_dump(thestorage);
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);
577
header_complex_parse_oid(testparse,
578
sizeof(testparse) / sizeof(oid), vars);
579
DEBUGMSGTL(("header_complex_test", "parse returned %d...\n", ret));