comparison packages/net/snmp/agent/current/src/agent_registry.c @ 103:95f3e12a6327 ecos-sw-2000-06-23

Merge from eCos master repository on 2000-06-23-16:41:10-BST
author jlarmour
date Fri, 23 Jun 2000 17:06:31 +0000
parents
children e0c0827131d1
comparison
equal deleted inserted replaced
102:6409b6d94dd7 103:95f3e12a6327
1 //==========================================================================
2 //
3 // ./agent/current/src/agent_registry.c
4 //
5 //
6 //==========================================================================
7 //####COPYRIGHTBEGIN####
8 //
9 // -------------------------------------------
10 // The contents of this file are subject to the Red Hat eCos Public License
11 // Version 1.1 (the "License"); you may not use this file except in
12 // compliance with the License. You may obtain a copy of the License at
13 // http://www.redhat.com/
14 //
15 // Software distributed under the License is distributed on an "AS IS"
16 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
17 // License for the specific language governing rights and limitations under
18 // the License.
19 //
20 // The Original Code is eCos - Embedded Configurable Operating System,
21 // released September 30, 1998.
22 //
23 // The Initial Developer of the Original Code is Red Hat.
24 // Portions created by Red Hat are
25 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
26 // All Rights Reserved.
27 // -------------------------------------------
28 //
29 //####COPYRIGHTEND####
30 //####UCDSNMPCOPYRIGHTBEGIN####
31 //
32 // -------------------------------------------
33 //
34 // Portions of this software may have been derived from the UCD-SNMP
35 // project, <http://ucd-snmp.ucdavis.edu/> from the University of
36 // California at Davis, which was originally based on the Carnegie Mellon
37 // University SNMP implementation. Portions of this software are therefore
38 // covered by the appropriate copyright disclaimers included herein.
39 //
40 // The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2"
41 // -------------------------------------------
42 //
43 //####UCDSNMPCOPYRIGHTEND####
44 //==========================================================================
45 //#####DESCRIPTIONBEGIN####
46 //
47 // Author(s): hmt
48 // Contributors: hmt
49 // Date: 2000-05-30
50 // Purpose: Port of UCD-SNMP distribution to eCos.
51 // Description:
52 //
53 //
54 //####DESCRIPTIONEND####
55 //
56 //==========================================================================
57 /********************************************************************
58 Copyright 1989, 1991, 1992 by Carnegie Mellon University
59
60 Derivative Work -
61 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
62
63 All Rights Reserved
64
65 Permission to use, copy, modify and distribute this software and its
66 documentation for any purpose and without fee is hereby granted,
67 provided that the above copyright notice appears in all copies and
68 that both that copyright notice and this permission notice appear in
69 supporting documentation, and that the name of CMU and The Regents of
70 the University of California not be used in advertising or publicity
71 pertaining to distribution of the software without specific written
72 permission.
73
74 CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
75 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
76 WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR
77 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
78 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
79 FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
80 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
81 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
82 *********************************************************************/
83 /*
84 * agent_registry.c
85 *
86 * Maintain a registry of MIB subtrees, together
87 * with related information regarding mibmodule, sessions, etc
88 */
89
90 #define IN_SNMP_VARS_C
91
92 #include <config.h>
93 #if HAVE_STRING_H
94 #include <string.h>
95 #endif
96 #if HAVE_STDLIB_H
97 #include <stdlib.h>
98 #endif
99 #include <sys/types.h>
100 #include <stdio.h>
101 #if HAVE_FCNTL_H
102 #include <fcntl.h>
103 #endif
104 #if HAVE_WINSOCK_H
105 #include <winsock.h>
106 #endif
107 #if TIME_WITH_SYS_TIME
108 # ifdef WIN32
109 # include <sys/timeb.h>
110 # else
111 # include <sys/time.h>
112 # endif
113 # include <time.h>
114 #else
115 # if HAVE_SYS_TIME_H
116 # include <sys/time.h>
117 # else
118 # include <time.h>
119 # endif
120 #endif
121
122 #if HAVE_DMALLOC_H
123 #include <dmalloc.h>
124 #endif
125
126 #include "mibincl.h"
127 #include "snmp_client.h"
128 #include "default_store.h"
129 #include "ds_agent.h"
130 #include "callback.h"
131 #include "agent_callbacks.h"
132 #include "agent_registry.h"
133 #include "snmp_alarm.h"
134
135 #include "snmpd.h"
136 #include "mibgroup/struct.h"
137 #include "mib_module_includes.h"
138
139 #ifdef USING_AGENTX_SUBAGENT_MODULE
140 #include "agentx/subagent.h"
141 #include "agentx/client.h"
142 #endif
143
144
145 struct snmp_index {
146 struct variable_list varbind; /* or pointer to var_list ? */
147 struct snmp_session *session; /* NULL implies unused ? */
148 struct snmp_index *next_oid;
149 struct snmp_index *prev_oid;
150 struct snmp_index *next_idx;
151 } *snmp_index_head = NULL;
152 struct subtree *subtrees;
153
154 int tree_compare(const struct subtree *ap, const struct subtree *bp)
155 {
156 return snmp_oid_compare(ap->name,ap->namelen,bp->name,bp->namelen);
157 }
158
159
160
161 /*
162 * Split the subtree into two at the specified point,
163 * returning the new (second) subtree
164 */
165 struct subtree *
166 split_subtree(struct subtree *current, oid name[], int name_len )
167 {
168 struct subtree *new_sub, *ptr;
169 int i;
170 char *cp;
171
172 if ( snmp_oid_compare(name, name_len,
173 current->end, current->end_len) > 0 )
174 return NULL; /* Split comes after the end of this subtree */
175
176 new_sub = (struct subtree *)malloc(sizeof(struct subtree));
177 if ( new_sub == NULL )
178 return NULL;
179 memcpy(new_sub, current, sizeof(struct subtree));
180
181 /* Set up the point of division */
182 memcpy(current->end, name, name_len*sizeof(oid));
183 memcpy(new_sub->start, name, name_len*sizeof(oid));
184 current->end_len = name_len;
185 new_sub->start_len = name_len;
186
187 /*
188 * Split the variables between the two new subtrees
189 */
190 i = current->variables_len;
191 current->variables_len = 0;
192
193 for ( ; i > 0 ; i-- ) {
194 /* Note that the variable "name" field omits
195 the prefix common to the whole registration,
196 hence the strange comparison here */
197 if ( snmp_oid_compare( new_sub->variables[0].name,
198 new_sub->variables[0].namelen,
199 name + current->namelen,
200 name_len - current->namelen ) >= 0 )
201 break; /* All following variables belong to the second subtree */
202
203 current->variables_len++;
204 new_sub->variables_len--;
205 cp = (char *)new_sub->variables;
206 new_sub->variables = (struct variable *)(cp + new_sub->variables_width);
207 }
208
209 /* Delegated trees should retain their variables regardless */
210 if ( current->variables_len > 0 &&
211 IS_DELEGATED((u_char)current->variables[0].type)) {
212 new_sub->variables_len = 1;
213 new_sub->variables = current->variables;
214 }
215
216 /* Propogate this split down through any children */
217 if ( current->children )
218 new_sub->children = split_subtree(current->children, name, name_len);
219
220 /* Retain the correct linking of the list */
221 for ( ptr = current ; ptr != NULL ; ptr=ptr->children )
222 ptr->next = new_sub;
223 for ( ptr = new_sub ; ptr != NULL ; ptr=ptr->children )
224 ptr->prev = current;
225 for ( ptr = new_sub->next ; ptr != NULL ; ptr=ptr->children )
226 ptr->prev = new_sub;
227
228 return new_sub;
229 }
230
231 int
232 load_subtree( struct subtree *new_sub )
233 {
234 struct subtree *tree1, *tree2, *new2;
235 struct subtree *prev, *next;
236 int res;
237
238 if ( new_sub == NULL )
239 return MIB_REGISTERED_OK; /* Degenerate case */
240
241 /*
242 * Find the subtree that contains the start of
243 * the new subtree (if any)...
244 */
245 tree1 = find_subtree( new_sub->start, new_sub->start_len, NULL );
246 /*
247 * ...and the subtree that follows the new one
248 * (NULL implies this is the final region covered)
249 */
250 if ( tree1 == NULL )
251 tree2 = find_subtree_next( new_sub->start, new_sub->start_len, NULL );
252 else
253 tree2 = tree1->next;
254
255
256 /*
257 * Handle new subtrees that start in virgin territory.
258 */
259 if ( tree1 == NULL ) {
260 new2 = NULL;
261 /* Is there any overlap with later subtrees ? */
262 if ( tree2 && snmp_oid_compare( new_sub->end, new_sub->end_len,
263 tree2->start, tree2->start_len ) > 0 )
264 new2 = split_subtree( new_sub, tree2->start, tree2->start_len );
265
266 /*
267 * Link the new subtree (less any overlapping region)
268 * with the list of existing registrations
269 */
270 if ( tree2 ) {
271 new_sub->prev = tree2->prev;
272 tree2->prev = new_sub;
273 }
274 else
275 new_sub->prev = find_subtree_previous( new_sub->start, new_sub->start_len, NULL );
276
277 if ( new_sub->prev )
278 new_sub->prev->next = new_sub;
279 else
280 subtrees = new_sub;
281
282 new_sub->next = tree2;
283
284 /*
285 * If there was any overlap,
286 * recurse to merge in the overlapping region
287 * (including anything that may follow the overlap)
288 */
289 if ( new2 )
290 return load_subtree( new2 );
291 }
292
293 else {
294 /*
295 * If the new subtree starts *within* an existing registration
296 * (rather than at the same point as it), then split the
297 * existing subtree at this point.
298 */
299 if ( snmp_oid_compare( new_sub->start, new_sub->start_len,
300 tree1->start, tree1->start_len) != 0 )
301 tree1 = split_subtree( tree1, new_sub->start, new_sub->start_len);
302 if ( tree1 == NULL )
303 return MIB_REGISTRATION_FAILED;
304
305 /* Now consider the end of this existing subtree:
306 * If it matches the new subtree precisely,
307 * simply merge the new one into the list of children
308 * If it includes the whole of the new subtree,
309 * split it at the appropriate point, and merge again
310 *
311 * If the new subtree extends beyond this existing region,
312 * split it, and recurse to merge the two parts.
313 */
314
315 switch ( snmp_oid_compare( new_sub->end, new_sub->end_len,
316 tree1->end, tree1->end_len)) {
317
318 case -1: /* Existing subtree contains new one */
319 (void) split_subtree( tree1,
320 new_sub->end, new_sub->end_len);
321 /* Fall Through */
322
323 case 0: /* The two trees match precisely */
324 /*
325 * Note: This is the only point where the original
326 * registration OID ("name") is used
327 */
328 prev = NULL;
329 next = tree1;
330 while ( next && next->namelen > new_sub->namelen ) {
331 prev = next;
332 next = next->children;
333 }
334 while ( next && next->namelen == new_sub->namelen &&
335 next->priority < new_sub->priority ) {
336 prev = next;
337 next = next->children;
338 }
339 if ( next && next->namelen == new_sub->namelen &&
340 next->priority == new_sub->priority )
341 return MIB_DUPLICATE_REGISTRATION;
342
343 if ( prev ) {
344 new_sub->children = next;
345 prev->children = new_sub;
346 new_sub->prev = prev->prev;
347 new_sub->next = prev->next;
348 }
349 else {
350 new_sub->children = next;
351 new_sub->prev = next->prev;
352 new_sub->next = next->next;
353
354 for ( next = new_sub->next ;
355 next != NULL ;
356 next = next->children )
357 next->prev = new_sub;
358
359 for ( prev = new_sub->prev ;
360 prev != NULL ;
361 prev = prev->children )
362 prev->next = new_sub;
363 }
364 break;
365
366 case 1: /* New subtree contains the existing one */
367 new2 = split_subtree( new_sub,
368 tree1->end, tree1->end_len);
369 res = load_subtree( new_sub );
370 if ( res != MIB_REGISTERED_OK )
371 return res;
372 return load_subtree( new2 );
373
374 }
375
376 }
377 return 0;
378 }
379
380
381 int
382 register_mib_range(const char *moduleName,
383 struct variable *var,
384 size_t varsize,
385 size_t numvars,
386 oid *mibloc,
387 size_t mibloclen,
388 int priority,
389 int range_subid,
390 oid range_ubound,
391 struct snmp_session *ss)
392 {
393 struct subtree *subtree, *sub2;
394 int res, i;
395 struct register_parameters reg_parms;
396
397 subtree = (struct subtree *) malloc(sizeof(struct subtree));
398 if ( subtree == NULL )
399 return MIB_REGISTRATION_FAILED;
400 memset(subtree, 0, sizeof(struct subtree));
401
402 DEBUGMSGTL(("register_mib", "registering \"%s\" at ", moduleName));
403 DEBUGMSGOID(("register_mib", mibloc, mibloclen));
404 DEBUGMSG(("register_mib","\n"));
405
406 /*
407 * Create the new subtree node being registered
408 */
409 memcpy(subtree->name, mibloc, mibloclen*sizeof(oid));
410 subtree->namelen = (u_char) mibloclen;
411 memcpy(subtree->start, mibloc, mibloclen*sizeof(oid));
412 subtree->start_len = (u_char) mibloclen;
413 memcpy(subtree->end, mibloc, mibloclen*sizeof(oid));
414 subtree->end[ mibloclen-1 ]++; /* XXX - or use 'variables' info ? */
415 subtree->end_len = (u_char) mibloclen;
416 memcpy(subtree->label, moduleName, strlen(moduleName)+1);
417 if ( var ) {
418 subtree->variables = (struct variable *) malloc(varsize*numvars);
419 memcpy(subtree->variables, var, numvars*varsize);
420 subtree->variables_len = numvars;
421 subtree->variables_width = varsize;
422 }
423 subtree->priority = priority;
424 subtree->session = ss;
425 res = load_subtree(subtree);
426
427 /*
428 * If registering a range,
429 * use the first subtree as a template
430 * for the rest of the range
431 */
432 if (( res == MIB_REGISTERED_OK ) && ( range_subid != 0 )) {
433 for ( i = mibloc[range_subid-1] +1 ; i < (int)range_ubound ; i++ ) {
434 sub2 = (struct subtree *) malloc(sizeof(struct subtree));
435 if ( sub2 == NULL ) {
436 unregister_mib_range( mibloc, mibloclen, priority,
437 range_subid, range_ubound);
438 return MIB_REGISTRATION_FAILED;
439 }
440 memcpy( sub2, subtree, sizeof(struct subtree));
441 sub2->start[range_subid-1] = i;
442 sub2->end[ range_subid-1] = i; /* XXX - ???? */
443 res = load_subtree(sub2);
444 if ( res != MIB_REGISTERED_OK ) {
445 unregister_mib_range( mibloc, mibloclen, priority,
446 range_subid, range_ubound);
447 return MIB_REGISTRATION_FAILED;
448 }
449 }
450 }
451
452
453 reg_parms.name = mibloc;
454 reg_parms.namelen = mibloclen;
455 reg_parms.priority = priority;
456 reg_parms.range_subid = range_subid;
457 reg_parms.range_ubound = range_ubound;
458 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REGISTER_OID,
459 &reg_parms);
460
461 return res;
462 }
463
464 int
465 register_mib_priority(const char *moduleName,
466 struct variable *var,
467 size_t varsize,
468 size_t numvars,
469 oid *mibloc,
470 size_t mibloclen,
471 int priority)
472 {
473 return register_mib_range( moduleName, var, varsize, numvars,
474 mibloc, mibloclen, priority, 0, 0, NULL );
475 }
476
477 int
478 register_mib(const char *moduleName,
479 struct variable *var,
480 size_t varsize,
481 size_t numvars,
482 oid *mibloc,
483 size_t mibloclen)
484 {
485 return register_mib_priority( moduleName, var, varsize, numvars,
486 mibloc, mibloclen, DEFAULT_MIB_PRIORITY );
487 }
488
489
490 void
491 unload_subtree( struct subtree *sub, struct subtree *prev)
492 {
493 struct subtree *ptr;
494
495 if ( prev != NULL ) { /* non-leading entries are easy */
496 prev->children = sub->children;
497 return;
498 }
499 /* otherwise, we need to amend our neighbours as well */
500
501 if ( sub->children == NULL) { /* just remove this node completely */
502 for (ptr = sub->prev ; ptr ; ptr=ptr->children )
503 ptr->next = sub->next;
504 for (ptr = sub->next ; ptr ; ptr=ptr->children )
505 ptr->prev = sub->prev;
506 return;
507 }
508 else {
509 for (ptr = sub->prev ; ptr ; ptr=ptr->children )
510 ptr->next = sub->children;
511 for (ptr = sub->next ; ptr ; ptr=ptr->children )
512 ptr->prev = sub->children;
513 return;
514 }
515 }
516
517 int
518 unregister_mib_range( oid *name, size_t len, int priority,
519 int range_subid, oid range_ubound)
520 {
521 struct subtree *list, *myptr;
522 struct subtree *prev, *child; /* loop through children */
523 struct register_parameters reg_parms;
524
525 list = find_subtree( name, len, subtrees );
526 if ( list == NULL )
527 return MIB_NO_SUCH_REGISTRATION;
528
529 for ( child=list, prev=NULL; child != NULL;
530 prev=child, child=child->children ) {
531 if (( snmp_oid_compare( child->name, child->namelen, name, len) == 0 )
532 && ( child->priority == priority ))
533 break; /* found it */
534 }
535 if ( child == NULL )
536 return MIB_NO_SUCH_REGISTRATION;
537
538 unload_subtree( child, prev );
539 myptr = child; /* remember this for later */
540
541 /*
542 * Now handle any occurances in the following subtrees,
543 * as a result of splitting this range. Due to the
544 * nature of the way such splits work, the first
545 * subtree 'slice' that doesn't refer to the given
546 * name marks the end of the original region.
547 *
548 * This should also serve to register ranges.
549 */
550
551 for ( list = myptr->next ; list != NULL ; list=list->next ) {
552 for ( child=list, prev=NULL; child != NULL;
553 prev=child, child=child->children ) {
554 if (( snmp_oid_compare( child->name, child->namelen,
555 name, len) == 0 )
556 && ( child->priority == priority )) {
557
558 unload_subtree( child, prev );
559 free_subtree( child );
560 break;
561 }
562 }
563 if ( child == NULL ) /* Didn't find the given name */
564 break;
565 }
566 free_subtree( myptr );
567
568 reg_parms.name = name;
569 reg_parms.namelen = len;
570 reg_parms.priority = priority;
571 reg_parms.range_subid = range_subid;
572 reg_parms.range_ubound = range_ubound;
573 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREGISTER_OID,
574 &reg_parms);
575
576 return MIB_UNREGISTERED_OK;
577 }
578
579 int
580 unregister_mib_priority(oid *name, size_t len, int priority)
581 {
582 return unregister_mib_range( name, len, priority, 0, 0 );
583 }
584
585 int
586 unregister_mib(oid *name,
587 size_t len)
588 {
589 return unregister_mib_priority( name, len, DEFAULT_MIB_PRIORITY );
590 }
591
592 void
593 unregister_mibs_by_session (struct snmp_session *ss)
594 {
595 struct subtree *list, *list2;
596 struct subtree *child, *prev, *next_child;
597
598 for( list = subtrees; list != NULL; list = list2) {
599 list2 = list->next;
600 for ( child=list, prev=NULL; child != NULL; child=next_child ) {
601
602 next_child = child->children;
603 if (( (ss->flags & SNMP_FLAGS_SUBSESSION) && child->session == ss ) ||
604 (!(ss->flags & SNMP_FLAGS_SUBSESSION) &&
605 child->session->subsession == ss )) {
606 unload_subtree( child, prev );
607 free_subtree( child );
608 }
609 else
610 prev = child;
611 }
612 }
613 }
614
615
616 struct subtree *
617 free_subtree(struct subtree *st)
618 {
619 struct subtree *ret = NULL;
620 if ((snmp_oid_compare(st->name, st->namelen, st->start, st->start_len) == 0)
621 && (st->variables != NULL))
622 free(st->variables);
623 if (st->next != NULL)
624 ret = st->next;
625 free(st);
626 return ret;
627 }
628
629 /* in_a_view: determines if a given snmp_pdu is allowed to see a
630 given name/namelen OID pointer
631 name IN - name of var, OUT - name matched
632 nameLen IN -number of sub-ids in name, OUT - subid-is in matched name
633 pi IN - relevant auth info re PDU
634 cvp IN - relevant auth info re mib module
635 */
636
637 int
638 in_a_view(oid *name, /* IN - name of var, OUT - name matched */
639 size_t *namelen, /* IN -number of sub-ids in name*/
640 struct snmp_pdu *pdu, /* IN - relevant auth info re PDU */
641 int type) /* IN - variable type being checked */
642 {
643
644 struct view_parameters view_parms;
645 view_parms.pdu = pdu;
646 view_parms.name = name;
647 if (namelen)
648 view_parms.namelen = *namelen;
649 else
650 view_parms.namelen = 0;
651 view_parms.errorcode = 0;
652
653 if (pdu->flags & UCD_MSG_FLAG_ALWAYS_IN_VIEW)
654 return 0; /* Enable bypassing of view-based access control */
655
656 /* check for v1 and counter64s, since snmpv1 doesn't support it */
657 if (pdu->version == SNMP_VERSION_1 && type == ASN_COUNTER64)
658 return 5;
659 switch (pdu->version) {
660 case SNMP_VERSION_1:
661 case SNMP_VERSION_2c:
662 case SNMP_VERSION_3:
663 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK,
664 &view_parms);
665 return view_parms.errorcode;
666 }
667 return 1;
668 }
669
670 /* in_a_view: determines if a given snmp_pdu is ever going to be allowed to do
671 anynthing or if it's not going to ever be authenticated. */
672 int
673 check_access(struct snmp_pdu *pdu) /* IN - pdu being checked */
674 {
675 struct view_parameters view_parms;
676 view_parms.pdu = pdu;
677 view_parms.name = 0;
678 view_parms.namelen = 0;
679 view_parms.errorcode = 0;
680
681 if (pdu->flags & UCD_MSG_FLAG_ALWAYS_IN_VIEW)
682 return 0; /* Enable bypassing of view-based access control */
683
684 switch (pdu->version) {
685 case SNMP_VERSION_1:
686 case SNMP_VERSION_2c:
687 case SNMP_VERSION_3:
688 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
689 SNMPD_CALLBACK_ACM_CHECK_INITIAL,
690 &view_parms);
691 return view_parms.errorcode;
692 }
693 return 1;
694 }
695
696 /* lexicographical compare two object identifiers.
697 * Returns -1 if name1 < name2,
698 * 0 if name1 = name2, or name1 matches name2 for length of name2
699 * 1 if name1 > name2
700 *
701 * Note: snmp_oid_compare checks len2 before last return.
702 */
703 int
704 compare_tree(const oid *in_name1,
705 size_t len1,
706 const oid *in_name2,
707 size_t len2)
708 {
709 register int len, res;
710 register const oid * name1 = in_name1;
711 register const oid * name2 = in_name2;
712
713 /* len = minimum of len1 and len2 */
714 if (len1 < len2)
715 len = len1;
716 else
717 len = len2;
718 /* find first non-matching OID */
719 while(len-- > 0){
720 res = *(name1++) - *(name2++);
721 if (res < 0)
722 return -1;
723 if (res > 0)
724 return 1;
725 }
726 /* both OIDs equal up to length of shorter OID */
727 if (len1 < len2)
728 return -1;
729
730 /* name1 matches name2 for length of name2, or they are equal */
731 return 0;
732 }
733
734 struct subtree *find_subtree_previous(oid *name,
735 size_t len,
736 struct subtree *subtree)
737 {
738 struct subtree *myptr, *previous = NULL;
739
740 if ( subtree )
741 myptr = subtree;
742 else
743 myptr = subtrees; /* look through everything */
744
745 for( ; myptr != NULL; previous = myptr, myptr = myptr->next) {
746 if (snmp_oid_compare(name, len, myptr->start, myptr->start_len) < 0)
747 return previous;
748 }
749 return previous;
750 }
751
752 struct subtree *find_subtree_next(oid *name,
753 size_t len,
754 struct subtree *subtree)
755 {
756 struct subtree *myptr = NULL;
757
758 myptr = find_subtree_previous(name, len, subtree);
759 if ( myptr != NULL ) {
760 myptr = myptr->next;
761 while ( myptr && (myptr->variables == NULL || myptr->variables_len == 0) )
762 myptr = myptr->next;
763 return myptr;
764 }
765 else if (subtree && snmp_oid_compare(name, len, subtree->start, subtree->start_len) < 0)
766 return subtree;
767 else
768 return NULL;
769 }
770
771 struct subtree *find_subtree(oid *name,
772 size_t len,
773 struct subtree *subtree)
774 {
775 struct subtree *myptr;
776
777 myptr = find_subtree_previous(name, len, subtree);
778 if (myptr && snmp_oid_compare(name, len, myptr->end, myptr->end_len) < 0)
779 return myptr;
780
781 return NULL;
782 }
783
784 struct snmp_session *get_session_for_oid( oid *name, size_t len)
785 {
786 struct subtree *myptr;
787
788 myptr = find_subtree_previous(name, len, subtrees);
789 while ( myptr && myptr->variables == NULL )
790 myptr = myptr->next;
791
792 if ( myptr == NULL )
793 return NULL;
794 else
795 return myptr->session;
796 }
797
798
799
800 static struct subtree root_subtrees[] = {
801 { { 0 }, 1 }, /* ccitt */
802 { { 1 }, 1 }, /* iso */
803 { { 2 }, 1 } /* joint-ccitt-iso */
804 };
805
806
807 void setup_tree (void)
808 {
809 #ifdef USING_AGENTX_SUBAGENT_MODULE
810 int role;
811
812 role = ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE);
813 ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, MASTER_AGENT);
814 #endif
815
816 register_mib("", NULL, 0, 0,
817 root_subtrees[0].name, root_subtrees[0].namelen);
818 register_mib("", NULL, 0, 0,
819 root_subtrees[1].name, root_subtrees[1].namelen);
820 register_mib("", NULL, 0, 0,
821 root_subtrees[2].name, root_subtrees[2].namelen);
822
823 /* Support for 'static' subtrees (subtrees_old) has now been dropped */
824
825 /* No longer necessary to sort the mib tree - this is inherent in
826 the construction of the subtree structure */
827
828 #ifdef USING_AGENTX_SUBAGENT_MODULE
829 ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, role);
830 #endif
831 }
832
833 /*
834 * Initial support for index allocation
835 */
836 extern struct snmp_session *main_session;
837
838 char *
839 register_string_index( oid *name, size_t name_len, char *cp )
840 {
841 struct variable_list varbind, *res;
842
843 memset( &varbind, 0, sizeof(struct variable_list));
844 varbind.type = ASN_OCTET_STR;
845 snmp_set_var_objid( &varbind, name, name_len );
846 if ( cp != ANY_STRING_INDEX ) {
847 snmp_set_var_value( &varbind, (u_char *)cp, strlen(cp) );
848 res = register_index( &varbind, ALLOCATE_THIS_INDEX, main_session );
849 }
850 else
851 res = register_index( &varbind, ALLOCATE_ANY_INDEX, main_session );
852
853 if ( res == NULL )
854 return NULL;
855 else
856 return (char *)res->val.string;
857 }
858
859 int
860 register_int_index( oid *name, size_t name_len, int val )
861 {
862 struct variable_list varbind, *res;
863
864 memset( &varbind, 0, sizeof(struct variable_list));
865 varbind.type = ASN_INTEGER;
866 snmp_set_var_objid( &varbind, name, name_len );
867 varbind.val.string = varbind.buf;
868 if ( val != ANY_INTEGER_INDEX ) {
869 varbind.val_len = sizeof(long);
870 *varbind.val.integer = val;
871 res = register_index( &varbind, ALLOCATE_THIS_INDEX, main_session );
872 }
873 else
874 res = register_index( &varbind, ALLOCATE_ANY_INDEX, main_session );
875
876 if ( res == NULL )
877 return -1;
878 else
879 return *res->val.integer;
880 }
881
882 struct variable_list *
883 register_oid_index( oid *name, size_t name_len,
884 oid *value, size_t value_len )
885 {
886 struct variable_list varbind;
887
888 memset( &varbind, 0, sizeof(struct variable_list));
889 varbind.type = ASN_OBJECT_ID;
890 snmp_set_var_objid( &varbind, name, name_len );
891 if ( value != ANY_OID_INDEX ) {
892 snmp_set_var_value( &varbind, (u_char*)value, value_len*sizeof(oid) );
893 return( register_index( &varbind, ALLOCATE_THIS_INDEX, main_session ));
894 }
895 else
896 return( register_index( &varbind, ALLOCATE_ANY_INDEX, main_session ));
897 }
898
899 struct variable_list*
900 register_index(struct variable_list *varbind, int flags, struct snmp_session *ss )
901 {
902 struct snmp_index *new_index, *idxptr, *idxptr2;
903 struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
904 int res, res2, i;
905
906 #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
907 if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == SUB_AGENT )
908 return( agentx_register_index( ss, varbind, flags ));
909 #endif
910 /* Look for the requested OID entry */
911 prev_oid_ptr = NULL;
912 prev_idx_ptr = NULL;
913 res = 1;
914 res2 = 1;
915 for( idxptr = snmp_index_head ; idxptr != NULL;
916 prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
917 if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
918 idxptr->varbind.name,
919 idxptr->varbind.name_length)) <= 0 )
920 break;
921 }
922
923 /* Found the OID - now look at the registered indices */
924 if ( res == 0 && idxptr ) {
925 if ( varbind->type != idxptr->varbind.type )
926 return NULL; /* wrong type */
927
928 /*
929 * If we've been asked for an arbitrary new value,
930 * then find the end of the list.
931 * If we've been asked for any arbitrary value,
932 * then look for an unused entry, and use that.
933 * If there aren't any, continue as for new.
934 * Otherwise, locate the given value in the (sorted)
935 * list of already allocated values
936 */
937 if ( flags & ALLOCATE_ANY_INDEX ) {
938 for(idxptr2 = idxptr ; idxptr2 != NULL;
939 prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
940 if ( flags == ALLOCATE_ANY_INDEX && idxptr2->session == NULL ) {
941 idxptr2->session = ss ;
942 return &idxptr2->varbind;
943 }
944 }
945 }
946 else {
947 for(idxptr2 = idxptr ; idxptr2 != NULL;
948 prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
949 switch ( varbind->type ) {
950 case ASN_INTEGER:
951 res2 = (*varbind->val.integer - *idxptr2->varbind.val.integer);
952 break;
953 case ASN_OCTET_STR:
954 i = SNMP_MIN(varbind->val_len, idxptr2->varbind.val_len);
955 res2 = memcmp(varbind->val.string, idxptr2->varbind.val.string, i);
956 break;
957 case ASN_OBJECT_ID:
958 res2 = snmp_oid_compare(varbind->val.objid, varbind->val_len/sizeof(oid),
959 idxptr2->varbind.val.objid,
960 idxptr2->varbind.val_len/sizeof(oid));
961 break;
962 default:
963 return NULL; /* wrong type */
964 }
965 if ( res2 <= 0 )
966 break;
967 }
968 if ( res2 == 0 )
969 return NULL; /* duplicate value */
970 }
971 }
972
973 /*
974 * OK - we've now located where the new entry needs to
975 * be fitted into the index registry tree
976 * To recap:
977 * 'prev_oid_ptr' points to the head of the OID index
978 * list prior to this one. If this is null, then
979 * it means that this is the first OID in the list.
980 * 'idxptr' points either to the head of this OID list,
981 * or the next OID (if this is a new OID request)
982 * These can be distinguished by the value of 'res'.
983 *
984 * 'prev_idx_ptr' points to the index entry that sorts
985 * immediately prior to the requested value (if any).
986 * If an arbitrary value is required, then this will
987 * point to the last allocated index.
988 * If this pointer is null, then either this is a new
989 * OID request, or the requested value is the first
990 * in the list.
991 * 'idxptr2' points to the next sorted index (if any)
992 * but is not actually needed any more.
993 *
994 * Clear? Good!
995 * I hope you've been paying attention.
996 * There'll be a test later :-)
997 */
998
999 /*
1000 * We proceed by creating the new entry
1001 * (by copying the entry provided)
1002 */
1003 new_index = (struct snmp_index *)malloc( sizeof( struct snmp_index ));
1004 if (new_index == NULL)
1005 return NULL;
1006 if (snmp_clone_var( varbind, &new_index->varbind ) != 0 ) {
1007 free( new_index );
1008 return NULL;
1009 }
1010 new_index->session = ss;
1011
1012 if ( varbind->type == ASN_OCTET_STR && flags == ALLOCATE_THIS_INDEX )
1013 new_index->varbind.val.string[new_index->varbind.val_len] = 0;
1014
1015 /*
1016 * If we've been given a value, then we can use that, but
1017 * otherwise, we need to create a new value for this entry.
1018 * Note that ANY_INDEX and NEW_INDEX are both covered by this
1019 * test (since NEW_INDEX & ANY_INDEX = ANY_INDEX, remember?)
1020 */
1021 if ( flags & ALLOCATE_ANY_INDEX ) {
1022 if ( prev_idx_ptr ) {
1023 if ( snmp_clone_var( &prev_idx_ptr->varbind, &new_index->varbind ) != 0 ) {
1024 free( new_index );
1025 return NULL;
1026 }
1027 }
1028 else
1029 new_index->varbind.val.string = new_index->varbind.buf;
1030
1031 switch ( varbind->type ) {
1032 case ASN_INTEGER:
1033 if ( prev_idx_ptr ) {
1034 (*new_index->varbind.val.integer)++;
1035 }
1036 else
1037 *(new_index->varbind.val.integer) = 1;
1038 new_index->varbind.val_len = sizeof(long);
1039 break;
1040 case ASN_OCTET_STR:
1041 if ( prev_idx_ptr ) {
1042 i = new_index->varbind.val_len-1;
1043 while ( new_index->varbind.buf[ i ] == 'z' ) {
1044 new_index->varbind.buf[ i ] = 'a';
1045 i--;
1046 if ( i < 0 ) {
1047 i = new_index->varbind.val_len;
1048 new_index->varbind.buf[ i ] = 'a';
1049 new_index->varbind.buf[ i+1 ] = 0;
1050 }
1051 }
1052 new_index->varbind.buf[ i ]++;
1053 }
1054 else
1055 strcpy((char *)new_index->varbind.buf, "aaaa");
1056 new_index->varbind.val_len = strlen((char *)new_index->varbind.buf);
1057 break;
1058 case ASN_OBJECT_ID:
1059 if ( prev_idx_ptr ) {
1060 i = prev_idx_ptr->varbind.val_len/sizeof(oid) -1;
1061 while ( new_index->varbind.val.objid[ i ] == 255 ) {
1062 new_index->varbind.val.objid[ i ] = 1;
1063 i--;
1064 if ( i == 0 && new_index->varbind.val.objid[0] == 2 ) {
1065 new_index->varbind.val.objid[ 0 ] = 1;
1066 i = new_index->varbind.val_len/sizeof(oid);
1067 new_index->varbind.val.objid[ i ] = 0;
1068 new_index->varbind.val_len += sizeof(oid);
1069 }
1070 }
1071 new_index->varbind.val.objid[ i ]++;
1072 }
1073 else {
1074 /* If the requested OID name is small enough,
1075 * append another OID (1) and use this as the
1076 * default starting value for new indexes.
1077 */
1078 if ( (varbind->name_length+1) * sizeof(oid) <= 40 ) {
1079 for ( i = 0 ; i < (int)varbind->name_length ; i++ )
1080 new_index->varbind.val.objid[i] = varbind->name[i];
1081 new_index->varbind.val.objid[varbind->name_length] = 1;
1082 new_index->varbind.val_len =
1083 (varbind->name_length+1) * sizeof(oid);
1084 }
1085 else {
1086 /* Otherwise use '.1.1.1.1...' */
1087 i = 40/sizeof(oid);
1088 if ( i > 4 )
1089 i = 4;
1090 new_index->varbind.val_len = i * (sizeof(oid));
1091 for (i-- ; i>=0 ; i-- )
1092 new_index->varbind.val.objid[i] = 1;
1093 }
1094 }
1095 break;
1096 default:
1097 free( new_index );
1098 return NULL; /* Index type not supported */
1099 }
1100 }
1101
1102 /*
1103 * Right - we've set up the new entry.
1104 * All that remains is to link it into the tree.
1105 * There are a number of possible cases here,
1106 * so watch carefully.
1107 */
1108 if ( prev_idx_ptr ) {
1109 new_index->next_idx = prev_idx_ptr->next_idx;
1110 new_index->next_oid = prev_idx_ptr->next_oid;
1111 prev_idx_ptr->next_idx = new_index;
1112 }
1113 else {
1114 if ( res == 0 && idxptr ) {
1115 new_index->next_idx = idxptr;
1116 new_index->next_oid = idxptr->next_oid;
1117 }
1118 else {
1119 new_index->next_idx = NULL;
1120 new_index->next_oid = idxptr;
1121 }
1122
1123 if ( prev_oid_ptr ) {
1124 while ( prev_oid_ptr ) {
1125 prev_oid_ptr->next_oid = new_index;
1126 prev_oid_ptr = prev_oid_ptr->next_idx;
1127 }
1128 }
1129 else
1130 snmp_index_head = new_index;
1131 }
1132 return &new_index->varbind;
1133 }
1134
1135 /*
1136 * Release an allocated index,
1137 * to allow it to be used elsewhere
1138 */
1139 int
1140 release_index(struct variable_list *varbind)
1141 {
1142 return( unregister_index( varbind, TRUE, NULL ));
1143 }
1144
1145 /*
1146 * Completely remove an allocated index,
1147 * due to errors in the registration process.
1148 */
1149 int
1150 remove_index(struct variable_list *varbind, struct snmp_session *ss)
1151 {
1152 return( unregister_index( varbind, FALSE, ss ));
1153 }
1154
1155 void
1156 unregister_index_by_session(struct snmp_session *ss)
1157 {
1158 struct snmp_index *idxptr, *idxptr2;
1159 for(idxptr = snmp_index_head ; idxptr != NULL; idxptr = idxptr->next_oid)
1160 for(idxptr2 = idxptr ; idxptr2 != NULL; idxptr2 = idxptr2->next_idx)
1161 if ( idxptr2->session == ss )
1162 idxptr2->session = NULL;
1163 }
1164
1165
1166 int
1167 unregister_index(struct variable_list *varbind, int remember, struct snmp_session *ss)
1168 {
1169 struct snmp_index *idxptr, *idxptr2;
1170 struct snmp_index *prev_oid_ptr, *prev_idx_ptr;
1171 int res, res2, i;
1172
1173 #if defined(USING_AGENTX_SUBAGENT_MODULE) && !defined(TESTING)
1174 if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) == SUB_AGENT )
1175 return( agentx_unregister_index( ss, varbind ));
1176 #endif
1177 /* Look for the requested OID entry */
1178 prev_oid_ptr = NULL;
1179 prev_idx_ptr = NULL;
1180 res = 1;
1181 res2 = 1;
1182 for( idxptr = snmp_index_head ; idxptr != NULL;
1183 prev_oid_ptr = idxptr, idxptr = idxptr->next_oid) {
1184 if ((res = snmp_oid_compare(varbind->name, varbind->name_length,
1185 idxptr->varbind.name,
1186 idxptr->varbind.name_length)) <= 0 )
1187 break;
1188 }
1189
1190 if ( res != 0 )
1191 return INDEX_ERR_NOT_ALLOCATED;
1192 if ( varbind->type != idxptr->varbind.type )
1193 return INDEX_ERR_WRONG_TYPE;
1194
1195 for(idxptr2 = idxptr ; idxptr2 != NULL;
1196 prev_idx_ptr = idxptr2, idxptr2 = idxptr2->next_idx) {
1197 i = SNMP_MIN(varbind->val_len, idxptr2->varbind.val_len);
1198 res2 = memcmp(varbind->val.string, idxptr2->varbind.val.string, i);
1199 if ( res2 <= 0 )
1200 break;
1201 }
1202 if ( res2 != 0 )
1203 return INDEX_ERR_NOT_ALLOCATED;
1204 if ( ss != idxptr2->session )
1205 return INDEX_ERR_WRONG_SESSION;
1206
1207 /*
1208 * If this is a "normal" index unregistration,
1209 * mark the index entry as unused, but leave
1210 * it in situ. This allows differentiation
1211 * between ANY_INDEX and NEW_INDEX
1212 */
1213 if ( remember ) {
1214 idxptr2->session = NULL; /* Unused index */
1215 return SNMP_ERR_NOERROR;
1216 }
1217 /*
1218 * If this is a failed attempt to register a
1219 * number of indexes, the successful ones
1220 * must be removed completely.
1221 */
1222 if ( prev_idx_ptr ) {
1223 prev_idx_ptr->next_idx = idxptr2->next_idx;
1224 }
1225 else if ( prev_oid_ptr ) {
1226 if ( idxptr2->next_idx ) /* Use p_idx_ptr as a temp variable */
1227 prev_idx_ptr = idxptr2->next_idx;
1228 else
1229 prev_idx_ptr = idxptr2->next_oid;
1230 while ( prev_oid_ptr ) {
1231 prev_oid_ptr->next_oid = prev_idx_ptr;
1232 prev_oid_ptr = prev_oid_ptr->next_idx;
1233 }
1234 }
1235 else {
1236 if ( idxptr2->next_idx )
1237 snmp_index_head = idxptr2->next_idx;
1238 else
1239 snmp_index_head = idxptr2->next_oid;
1240 }
1241 snmp_free_var( (struct variable_list *)idxptr2 );
1242 return SNMP_ERR_NOERROR;
1243 }
1244
1245
1246 void dump_registry( void )
1247 {
1248 struct subtree *myptr, *myptr2;
1249 struct snmp_index *idxptr, *idxptr2;
1250 char start_oid[SPRINT_MAX_LEN];
1251 char end_oid[SPRINT_MAX_LEN];
1252
1253 for( myptr = subtrees ; myptr != NULL; myptr = myptr->next) {
1254 sprint_objid(start_oid, myptr->start, myptr->start_len);
1255 sprint_objid(end_oid, myptr->end, myptr->end_len);
1256 printf("%c %s - %s %c\n",
1257 ( myptr->variables ? ' ' : '(' ),
1258 start_oid, end_oid,
1259 ( myptr->variables ? ' ' : ')' ));
1260 for( myptr2 = myptr ; myptr2 != NULL; myptr2 = myptr2->children) {
1261 if ( myptr2->label && myptr2->label[0] )
1262 printf("\t%s\n", myptr2->label);
1263 }
1264 }
1265
1266 if ( snmp_index_head )
1267 printf("\nIndex Allocations:\n");
1268 for( idxptr = snmp_index_head ; idxptr != NULL; idxptr = idxptr->next_oid) {
1269 sprint_objid(start_oid, idxptr->varbind.name, idxptr->varbind.name_length);
1270 printf("%s indexes:\n", start_oid);
1271 for( idxptr2 = idxptr ; idxptr2 != NULL; idxptr2 = idxptr2->next_idx) {
1272 switch( idxptr2->varbind.type ) {
1273 case ASN_INTEGER:
1274 printf(" %c %ld %c\n",
1275 ( idxptr2->session ? ' ' : '(' ),
1276 *idxptr2->varbind.val.integer,
1277 ( idxptr2->session ? ' ' : ')' ));
1278 break;
1279 case ASN_OCTET_STR:
1280 printf(" %c %s %c\n",
1281 ( idxptr2->session ? ' ' : '(' ),
1282 idxptr2->varbind.val.string,
1283 ( idxptr2->session ? ' ' : ')' ));
1284 break;
1285 case ASN_OBJECT_ID:
1286 sprint_objid(end_oid, idxptr2->varbind.val.objid,
1287 idxptr2->varbind.val_len/sizeof(oid));
1288 printf(" %c %s %c\n",
1289 ( idxptr2->session ? ' ' : '(' ),
1290 end_oid,
1291 ( idxptr2->session ? ' ' : ')' ));
1292 break;
1293 default:
1294 printf("unsupported type (%d)\n",
1295 idxptr2->varbind.type);
1296 }
1297 }
1298 }
1299 }
1300
1301 #ifdef TESTING
1302 struct variable_list varbind;
1303 struct snmp_session main_sess, *main_session=&main_sess;
1304
1305 void
1306 test_string_register( int n, char *cp )
1307 {
1308 varbind.name[4] = n;
1309 if (register_string_index(varbind.name, varbind.name_length, cp) == NULL)
1310 printf("allocating %s failed\n", cp);
1311 }
1312
1313 void
1314 test_int_register( int n, int val )
1315 {
1316 varbind.name[4] = n;
1317 if (register_int_index( varbind.name, varbind.name_length, val ) == -1 )
1318 printf("allocating %d/%d failed\n", n, val);
1319 }
1320
1321 void
1322 test_oid_register( int n, int subid )
1323 {
1324 struct variable_list *res;
1325
1326 varbind.name[4] = n;
1327 if ( subid != -1 ) {
1328 varbind.val.objid[5] = subid;
1329 res = register_oid_index(varbind.name, varbind.name_length,
1330 varbind.val.objid,
1331 varbind.val_len/sizeof(oid) );
1332 }
1333 else
1334 res = register_oid_index(varbind.name, varbind.name_length, NULL, 0);
1335
1336 if (res == NULL )
1337 printf("allocating %d/%d failed\n", n, subid);
1338 }
1339
1340 void
1341 main( int argc, char argv[] )
1342 {
1343 oid name[] = { 1, 2, 3, 4, 0 };
1344 int i;
1345
1346 memset( &varbind, 0, sizeof(struct variable_list));
1347 snmp_set_var_objid( &varbind, name, 5 );
1348 varbind.type = ASN_OCTET_STR;
1349 /*
1350 * Test index structure linking:
1351 * a) sorted by OID
1352 */
1353 test_string_register( 20, "empty OID" );
1354 test_string_register( 10, "first OID" );
1355 test_string_register( 40, "last OID" );
1356 test_string_register( 30, "middle OID" );
1357
1358 /*
1359 * b) sorted by index value
1360 */
1361 test_string_register( 25, "eee: empty IDX" );
1362 test_string_register( 25, "aaa: first IDX" );
1363 test_string_register( 25, "zzz: last IDX" );
1364 test_string_register( 25, "mmm: middle IDX" );
1365 printf("This next one should fail....\n");
1366 test_string_register( 25, "eee: empty IDX" ); /* duplicate */
1367 printf("done\n");
1368
1369 /*
1370 * c) test initial index linking
1371 */
1372 test_string_register( 5, "eee: empty initial IDX" );
1373 test_string_register( 5, "aaa: replace initial IDX" );
1374
1375 /*
1376 * Did it all work?
1377 */
1378 dump_registry();
1379 unregister_index_by_session( main_session );
1380 /*
1381 * Now test index allocation
1382 * a) integer values
1383 */
1384 test_int_register( 110, -1 ); /* empty */
1385 test_int_register( 110, -1 ); /* append */
1386 test_int_register( 110, 10 ); /* append exact */
1387 printf("This next one should fail....\n");
1388 test_int_register( 110, 10 ); /* exact duplicate */
1389 printf("done\n");
1390 test_int_register( 110, -1 ); /* append */
1391 test_int_register( 110, 5 ); /* insert exact */
1392
1393 /*
1394 * b) string values
1395 */
1396 test_string_register( 120, NULL ); /* empty */
1397 test_string_register( 120, NULL ); /* append */
1398 test_string_register( 120, "aaaz" );
1399 test_string_register( 120, NULL ); /* minor rollover */
1400 test_string_register( 120, "zzzz" );
1401 test_string_register( 120, NULL ); /* major rollover */
1402
1403 /*
1404 * c) OID values
1405 */
1406
1407 test_oid_register( 130, -1 ); /* empty */
1408 test_oid_register( 130, -1 ); /* append */
1409
1410 varbind.val_len = varbind.name_length*sizeof(oid);
1411 memcpy( varbind.buf, varbind.name, varbind.val_len);
1412 varbind.val.objid = (oid*) varbind.buf;
1413 varbind.val_len += sizeof(oid);
1414
1415 test_oid_register( 130, 255 ); /* append exact */
1416 test_oid_register( 130, -1 ); /* minor rollover */
1417 test_oid_register( 130, 100 ); /* insert exact */
1418 printf("This next one should fail....\n");
1419 test_oid_register( 130, 100 ); /* exact duplicate */
1420 printf("done\n");
1421
1422 varbind.val.objid = (oid*)varbind.buf;
1423 for ( i=0; i<6; i++ )
1424 varbind.val.objid[i]=255;
1425 varbind.val.objid[0]=1;
1426 test_oid_register( 130, 255 ); /* set up rollover */
1427 test_oid_register( 130, -1 ); /* medium rollover */
1428
1429 for ( i=0; i<6; i++ )
1430 varbind.val.objid[i]=255;
1431 varbind.val.objid[0]=2;
1432 test_oid_register( 130, 255 ); /* set up rollover */
1433 test_oid_register( 130, -1 ); /* major rollover */
1434
1435 /*
1436 * Did it all work?
1437 */
1438 dump_registry();
1439
1440 /*
1441 * Test the various "invalid" requests
1442 * (unsupported types, mis-matched types, etc)
1443 */
1444 printf("The rest of these should fail....\n");
1445 test_oid_register( 110, -1 );
1446 test_oid_register( 110, 100 );
1447 test_oid_register( 120, -1 );
1448 test_oid_register( 120, 100 );
1449 test_string_register( 110, NULL );
1450 test_string_register( 110, "aaaa" );
1451 test_string_register( 130, NULL );
1452 test_string_register( 130, "aaaa" );
1453 test_int_register( 120, -1 );
1454 test_int_register( 120, 1 );
1455 test_int_register( 130, -1 );
1456 test_int_register( 130, 1 );
1457 printf("done - this dump should be the same as before\n");
1458 dump_registry();
1459 }
1460 #endif