OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [snmp/] [agent/] [current/] [src/] [agent_registry.c] - Blame information for rev 786

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.