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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [snmp/] [agent/] [current/] [src/] [snmp_agent.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/snmp_agent.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
 * snmp_agent.c
93
 *
94
 * Simple Network Management Protocol (RFC 1067).
95
 */
96
/***********************************************************
97
        Copyright 1988, 1989 by Carnegie Mellon University
98
 
99
                      All Rights Reserved
100
 
101
Permission to use, copy, modify, and distribute this software and its
102
documentation for any purpose and without fee is hereby granted,
103
provided that the above copyright notice appear in all copies and that
104
both that copyright notice and this permission notice appear in
105
supporting documentation, and that the name of CMU not be
106
used in advertising or publicity pertaining to distribution of the
107
software without specific, written prior permission.
108
 
109
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
110
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
111
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
112
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
113
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
114
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
115
SOFTWARE.
116
******************************************************************/
117
 
118
#include <config.h>
119
 
120
#include <sys/types.h>
121
#ifdef HAVE_STDLIB_H
122
#include <stdlib.h>
123
#endif
124
#if HAVE_UNISTD_H
125
#include <unistd.h>
126
#endif
127
#if HAVE_STRING_H
128
#include <string.h>
129
#endif
130
#if TIME_WITH_SYS_TIME
131
# ifdef WIN32
132
#  include <sys/timeb.h>
133
# else
134
#  include <sys/time.h>
135
# endif
136
# include <time.h>
137
#else
138
# if HAVE_SYS_TIME_H
139
#  include <sys/time.h>
140
# else
141
#  include <time.h>
142
# endif
143
#endif
144
#if HAVE_SYS_SELECT_H
145
#include <sys/select.h>
146
#endif
147
#if HAVE_NETINET_IN_H
148
#include <netinet/in.h>
149
#endif
150
#include <errno.h>
151
#if HAVE_WINSOCK_H
152
#include <winsock.h>
153
#endif
154
 
155
#if HAVE_DMALLOC_H
156
#include <dmalloc.h>
157
#endif
158
 
159
#include "asn1.h"
160
#define SNMP_NEED_REQUEST_LIST
161
#include "snmp_api.h"
162
#include "snmp_impl.h"
163
#include "snmp.h"
164
#include "mib.h"
165
#include "snmp_client.h"
166
 
167
#include "snmp_vars.h"
168
#include "snmpd.h"
169
#include "mibgroup/struct.h"
170
#include "mibgroup/util_funcs.h"
171
#include "var_struct.h"
172
#include "read_config.h"
173
#include "snmp_logging.h"
174
#include "snmp_debug.h"
175
#include "mib_module_config.h"
176
 
177
#include "default_store.h"
178
#include "ds_agent.h"
179
#include "snmp_agent.h"
180
#include "agent_trap.h"
181
 
182
static int snmp_vars_inc;
183
 
184
static struct agent_snmp_session *agent_session_list = NULL;
185
 
186
 
187
static void dump_var(oid *, size_t, int, void *, size_t);
188
static int goodValue(u_char, size_t, u_char, size_t);
189
static void setVariable(u_char *, u_char, size_t, u_char *, size_t);
190
 
191
static void dump_var (
192
    oid *var_name,
193
    size_t var_name_len,
194
    int statType,
195
    void *statP,
196
    size_t statLen)
197
{
198
    char buf [SPRINT_MAX_LEN];
199
    struct variable_list temp_var;
200
 
201
    temp_var.type = statType;
202
    temp_var.val.string = (u_char *)statP;
203
    temp_var.val_len = statLen;
204
    sprint_variable (buf, var_name, var_name_len, &temp_var);
205
    snmp_log(LOG_INFO, "    >> %s\n", buf);
206
}
207
 
208
 
209
int getNextSessID()
210
{
211
    static int SessionID = 0;
212
 
213
    return ++SessionID;
214
}
215
 
216
int
217
agent_check_and_process(int block) {
218
  int numfds;
219
  fd_set fdset;
220
  struct timeval        timeout, *tvp = &timeout;
221
  int count;
222
  int fakeblock=0;
223
 
224
  tvp =  &timeout;
225
  tvp->tv_sec  = 0;
226
  tvp->tv_usec = 0;
227
 
228
  numfds = 0;
229
  FD_ZERO(&fdset);
230
  snmp_select_info(&numfds, &fdset, tvp, &fakeblock);
231
  if (block == 1 && fakeblock == 1)
232
    tvp = NULL; /* block without timeout */
233
  else if (block == 0) {
234
      tvp->tv_sec = 0;
235
      tvp->tv_usec = 0;
236
  }
237
 
238
  count = select(numfds, &fdset, 0, 0, tvp);
239
 
240
  if (count > 0){
241
    /* packets found, process them */
242
    snmp_read(&fdset);
243
  } else switch(count){
244
    case 0:
245
      snmp_timeout();
246
      break;
247
    case -1:
248
      if (errno == EINTR){
249
        return -1;
250
      } else {
251
        snmp_log_perror("select");
252
      }
253
      return -1;
254
    default:
255
      snmp_log(LOG_ERR, "select returned %d\n", count);
256
      return -1;
257
  }  /* endif -- count>0 */
258
  return count;
259
}
260
 
261
 
262
/*
263
 * The session is created using the "traditional API" routine snmp_open()
264
 * so is linked into the global library Sessions list.  It also opens a
265
 * socket that listens for incoming requests.
266
 *
267
 *   The agent runs in an infinite loop (in the 'receive()' routine),
268
 * which calls snmp_read() when such a request is received on this socket.
269
 * This routine then traverses the library 'Sessions' list to identify the
270
 * relevant session and eventually invokes '_sess_read'.
271
 *   This then processes the incoming packet, calling the pre_parse, parse,
272
 * post_parse and callback routines in turn.
273
 */
274
 
275
        /* Global access to the primary session structure for this agent.
276
                for Index Allocation use initially. */
277
struct snmp_session *main_session;
278
 
279
int
280
init_master_agent(int dest_port,
281
                  int (*pre_parse) (struct snmp_session *, snmp_ipaddr),
282
                  int (*post_parse) (struct snmp_session *, struct snmp_pdu *,int))
283
{
284
    struct snmp_session sess, *session;
285
 
286
    if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) != MASTER_AGENT )
287
        return 0; /* no error if ! MASTER_AGENT */
288
 
289
    DEBUGMSGTL(("snmpd","installing master agent on port %d\n", dest_port));
290
 
291
    snmp_sess_init( &sess );
292
 
293
    sess.version = SNMP_DEFAULT_VERSION;
294
    sess.peername = SNMP_DEFAULT_PEERNAME;
295
    sess.community_len = SNMP_DEFAULT_COMMUNITY_LEN;
296
 
297
    sess.local_port = dest_port;
298
    sess.callback = handle_snmp_packet;
299
    sess.authenticator = NULL;
300
    sess.flags = ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS);
301
    session = snmp_open_ex( &sess, pre_parse, 0, post_parse, 0, 0 );
302
 
303
    if ( session == NULL ) {
304
      /* diagnose snmp_open errors with the input struct snmp_session pointer */
305
        snmp_sess_perror("init_master_agent", &sess);
306
                return 1;
307
    }
308
    main_session = session;
309
        return 0;
310
}
311
 
312
struct agent_snmp_session  *
313
init_agent_snmp_session( struct snmp_session *session, struct snmp_pdu *pdu )
314
{
315
    struct agent_snmp_session  *asp;
316
 
317
    asp = malloc( sizeof( struct agent_snmp_session ));
318
    if ( asp == NULL )
319
        return NULL;
320
    asp->start = pdu->variables;
321
    asp->end   = pdu->variables;
322
    if ( asp->end != NULL )
323
        while ( asp->end->next_variable != NULL )
324
            asp->end = asp->end->next_variable;
325
    asp->session = session;
326
    asp->pdu     = pdu;
327
    asp->rw      = READ;
328
    asp->exact   = TRUE;
329
    asp->outstanding_requests = NULL;
330
    asp->next    = NULL;
331
    asp->mode    = RESERVE1;
332
    asp->status  = SNMP_ERR_NOERROR;
333
 
334
    return asp;
335
}
336
 
337
int
338
count_varbinds( struct snmp_pdu *pdu )
339
{
340
  int count = 0;
341
  struct variable_list *var_ptr;
342
 
343
  for ( var_ptr = pdu->variables ; var_ptr != NULL ;
344
                        var_ptr = var_ptr->next_variable )
345
        count++;
346
 
347
  return count;
348
}
349
 
350
int
351
handle_snmp_packet(int operation, struct snmp_session *session, int reqid,
352
                   struct snmp_pdu *pdu, void *magic)
353
{
354
    struct agent_snmp_session  *asp;
355
    int status, allDone, i;
356
    struct variable_list *var_ptr, *var_ptr2;
357
 
358
    if ( magic == NULL ) {
359
        asp = init_agent_snmp_session( session, snmp_clone_pdu(pdu) );
360
        status = SNMP_ERR_NOERROR;
361
    }
362
    else {
363
        asp = (struct agent_snmp_session *)magic;
364
        status =   asp->status;
365
    }
366
 
367
    if (asp->outstanding_requests != NULL)
368
        return 1;
369
 
370
    if ( check_access(pdu) != 0) {
371
        /* access control setup is incorrect */
372
        send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
373
        if (asp->pdu->version != SNMP_VERSION_1 && asp->pdu->version != SNMP_VERSION_2c) {
374
            asp->pdu->errstat = SNMP_ERR_AUTHORIZATIONERROR;
375
            asp->pdu->command = SNMP_MSG_RESPONSE;
376
            snmp_increment_statistic(STAT_SNMPOUTPKTS);
377
            snmp_send( asp->session, asp->pdu );
378
            free( asp );
379
            return 1;
380
        } else {
381
            /* drop the request */
382
            free( asp );
383
            return 0;
384
        }
385
    }
386
 
387
    switch (pdu->command) {
388
    case SNMP_MSG_GET:
389
        if ( asp->mode != RESERVE1 )
390
            break;                      /* Single pass */
391
        snmp_increment_statistic(STAT_SNMPINGETREQUESTS);
392
        status = handle_next_pass( asp );
393
        asp->mode = RESERVE2;
394
        break;
395
 
396
    case SNMP_MSG_GETNEXT:
397
        if ( asp->mode != RESERVE1 )
398
            break;                      /* Single pass */
399
        snmp_increment_statistic(STAT_SNMPINGETNEXTS);
400
        asp->exact   = FALSE;
401
        status = handle_next_pass( asp );
402
        asp->mode = RESERVE2;
403
        break;
404
 
405
    case SNMP_MSG_GETBULK:
406
            /*
407
             * GETBULKS require multiple passes. The first pass handles the
408
             * explicitly requested varbinds, and subsequent passes append
409
             * to the existing var_op_list.  Each pass (after the first)
410
             * uses the results of the preceeding pass as the input list
411
             * (delimited by the start & end pointers.
412
             * Processing is terminated if all entries in a pass are
413
             * EndOfMib, or the maximum number of repetitions are made.
414
             */
415
        if ( asp->mode == RESERVE1 ) {
416
            snmp_increment_statistic(STAT_SNMPINGETREQUESTS);
417
            asp->exact   = FALSE;
418
                    /*
419
                     * Limit max repetitions to something reasonable
420
                     *  XXX: We should figure out what will fit somehow...
421
                     */
422
            if ( asp->pdu->errindex > 100 )
423
                asp->pdu->errindex = 100;
424
 
425
            status = handle_next_pass( asp );   /* First pass */
426
            asp->mode = RESERVE2;
427
            if ( status != SNMP_ERR_NOERROR )
428
                break;
429
 
430
            while ( asp->pdu->errstat-- > 0 )    /* Skip non-repeaters */
431
                asp->start = asp->start->next_variable;
432
            asp->pdu->errindex--;           /* Handled first repetition */
433
 
434
            if ( asp->outstanding_requests != NULL )
435
                return 1;
436
        }
437
 
438
        while ( asp->pdu->errindex-- > 0 ) {     /* Process repeaters */
439
                /*
440
                 * Add new variable structures for the
441
                 * repeating elements, ready for the next pass.
442
                 * Also check that these are not all EndOfMib
443
                 */
444
            allDone = TRUE;             /* Check for some content */
445
            for ( var_ptr = asp->start;
446
                  var_ptr != asp->end->next_variable;
447
                  var_ptr = var_ptr->next_variable ) {
448
                                /* XXX: we don't know the size of the next
449
                                        OID, so assume the maximum length */
450
                if ( var_ptr->type != SNMP_ENDOFMIBVIEW )
451
                {
452
                var_ptr2 = snmp_add_null_var(asp->pdu, var_ptr->name, MAX_OID_LEN);
453
                for ( i=var_ptr->name_length ; i<MAX_OID_LEN ; i++)
454
                    var_ptr2->name[i] = 0;
455
                var_ptr2->name_length = var_ptr->name_length;
456
 
457
                    allDone = FALSE;
458
                }
459
            }
460
            if ( allDone )
461
                break;
462
 
463
            asp->start = asp->end->next_variable;
464
            while ( asp->end->next_variable != NULL )
465
                asp->end = asp->end->next_variable;
466
 
467
            status = handle_next_pass( asp );
468
            if ( status != SNMP_ERR_NOERROR )
469
                break;
470
            if ( asp->outstanding_requests != NULL )
471
                return 1;
472
        }
473
        break;
474
 
475
    case SNMP_MSG_SET:
476
            /*
477
             * SETS require 3-4 passes through the var_op_list.  The first two
478
             * passes verify that all types, lengths, and values are valid
479
             * and may reserve resources and the third does the set and a
480
             * fourth executes any actions.  Then the identical GET RESPONSE
481
             * packet is returned.
482
             * If either of the first two passes returns an error, another
483
             * pass is made so that any reserved resources can be freed.
484
             * If the third pass returns an error, another pass is made so that
485
             * any changes can be reversed.
486
             * If the fourth pass (or any of the error handling passes)
487
             * return an error, we'd rather not know about it!
488
             */
489
        if ( asp->mode == RESERVE1 ) {
490
            snmp_increment_statistic(STAT_SNMPINSETREQUESTS);
491
            asp->rw      = WRITE;
492
 
493
            status = handle_next_pass( asp );
494
 
495
            if ( status != SNMP_ERR_NOERROR )
496
                asp->mode = FREE;
497
            else
498
                asp->mode = RESERVE2;
499
 
500
            if ( asp->outstanding_requests != NULL )
501
                return 1;
502
        }
503
 
504
        if ( asp->mode == RESERVE2 ) {
505
            status = handle_next_pass( asp );
506
 
507
            if ( status != SNMP_ERR_NOERROR )
508
                asp->mode = FREE;
509
            else
510
                asp->mode = ACTION;
511
 
512
            if ( asp->outstanding_requests != NULL )
513
                return 1;
514
        }
515
 
516
        if ( asp->mode == ACTION ) {
517
            status = handle_next_pass( asp );
518
 
519
            if ( status != SNMP_ERR_NOERROR )
520
                asp->mode = UNDO;
521
            else
522
                asp->mode = COMMIT;
523
 
524
            if ( asp->outstanding_requests != NULL )
525
                return 1;
526
        }
527
 
528
        if ( asp->mode == COMMIT ) {
529
            status = handle_next_pass( asp );
530
 
531
            if ( status != SNMP_ERR_NOERROR ) {
532
                status    = SNMP_ERR_COMMITFAILED;
533
                asp->mode = FINISHED_FAILURE;
534
            }
535
            else
536
                asp->mode = FINISHED_SUCCESS;
537
 
538
            if ( asp->outstanding_requests != NULL )
539
                return 1;
540
        }
541
 
542
        if ( asp->mode == UNDO ) {
543
            if (handle_next_pass( asp ) != SNMP_ERR_NOERROR )
544
                status = SNMP_ERR_UNDOFAILED;
545
 
546
            asp->mode = FINISHED_FAILURE;
547
            break;
548
        }
549
 
550
        if ( asp->mode == FREE ) {
551
            (void) handle_next_pass( asp );
552
            break;
553
        }
554
 
555
        break;
556
 
557
    case SNMP_MSG_RESPONSE:
558
        snmp_increment_statistic(STAT_SNMPINGETRESPONSES);
559
        free( asp );
560
        return 0;
561
    case SNMP_MSG_TRAP:
562
    case SNMP_MSG_TRAP2:
563
        snmp_increment_statistic(STAT_SNMPINTRAPS);
564
        free( asp );
565
        return 0;
566
    default:
567
        snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
568
        free( asp );
569
        return 0;
570
    }
571
 
572
    if ( asp->outstanding_requests != NULL ) {
573
        asp->status = status;
574
        asp->next = agent_session_list;
575
        agent_session_list = asp;
576
    }
577
    else {
578
                /*
579
                 * May need to "dumb down" a SET error status for a
580
                 *  v1 query.  See RFC2576 - section 4.3
581
                 */
582
        if (( asp->pdu->command == SNMP_MSG_SET ) &&
583
            ( asp->pdu->version == SNMP_VERSION_1 )) {
584
            switch ( status ) {
585
                case SNMP_ERR_WRONGVALUE:
586
                case SNMP_ERR_WRONGENCODING:
587
                case SNMP_ERR_WRONGTYPE:
588
                case SNMP_ERR_WRONGLENGTH:
589
                case SNMP_ERR_INCONSISTENTVALUE:
590
                        status = SNMP_ERR_BADVALUE;
591
                        break;
592
                case SNMP_ERR_NOACCESS:
593
                case SNMP_ERR_NOTWRITABLE:
594
                case SNMP_ERR_NOCREATION:
595
                case SNMP_ERR_INCONSISTENTNAME:
596
                case SNMP_ERR_AUTHORIZATIONERROR:
597
                        status = SNMP_ERR_NOSUCHNAME;
598
                        break;
599
                case SNMP_ERR_RESOURCEUNAVAILABLE:
600
                case SNMP_ERR_COMMITFAILED:
601
                case SNMP_ERR_UNDOFAILED:
602
                        status = SNMP_ERR_GENERR;
603
                        break;
604
            }
605
        }
606
                /*
607
                 * Similarly we may need to "dumb down" v2 exception
608
                 *  types to throw an error for a v1 query.
609
                 *  See RFC2576 - section 4.1.2.3
610
                 */
611
        if (( asp->pdu->command != SNMP_MSG_SET ) &&
612
            ( asp->pdu->version == SNMP_VERSION_1 )) {
613
                for ( var_ptr = asp->pdu->variables, i=0 ;
614
                        var_ptr != NULL ;
615
                        var_ptr = var_ptr->next_variable, i++ ) {
616
                    switch ( var_ptr->type ) {
617
                        case SNMP_NOSUCHOBJECT:
618
                        case SNMP_NOSUCHINSTANCE:
619
                        case SNMP_ENDOFMIBVIEW:
620
                        case ASN_COUNTER64:
621
                                status = SNMP_ERR_NOSUCHNAME;
622
                                asp->pdu->errindex=i;
623
                                break;
624
                    }
625
                }
626
        }
627
        if ( status == SNMP_ERR_NOERROR ) {
628
            snmp_increment_statistic_by(
629
                (asp->pdu->command == SNMP_MSG_SET ?
630
                        STAT_SNMPINTOTALSETVARS : STAT_SNMPINTOTALREQVARS ),
631
                count_varbinds( asp->pdu ));
632
        }
633
        else {
634
                /*
635
                 * Use a copy of the original request
636
                 *   to report failures.
637
                 */
638
            i = asp->pdu->errindex;
639
            snmp_free_pdu( asp->pdu );
640
            asp->pdu = snmp_clone_pdu( pdu );
641
            asp->pdu->errindex = i;
642
        }
643
        asp->pdu->command = SNMP_MSG_RESPONSE;
644
        asp->pdu->errstat = status;
645
        snmp_send( asp->session, asp->pdu );
646
        snmp_increment_statistic(STAT_SNMPOUTPKTS);
647
        snmp_increment_statistic(STAT_SNMPOUTGETRESPONSES);
648
        free( asp );
649
    }
650
 
651
    return 1;
652
}
653
 
654
 
655
int
656
handle_next_pass(struct agent_snmp_session  *asp)
657
{
658
    int status;
659
    struct snmp_pdu *pdu = asp->pdu;
660
    struct request_list *req_p, *next_req;
661
 
662
 
663
        if ( asp->outstanding_requests != NULL )
664
            return SNMP_ERR_NOERROR;
665
        status = handle_var_list( asp );
666
        if ( asp->outstanding_requests != NULL ) {
667
            if ( status == SNMP_ERR_NOERROR ) {
668
                /* Send out any subagent requests */
669
                for ( req_p = asp->outstanding_requests ;
670
                        req_p != NULL ; req_p = req_p->next_request ) {
671
 
672
                    snmp_async_send( req_p->session,  req_p->pdu,
673
                                      req_p->callback, req_p->cb_data );
674
                }
675
                asp->pdu = snmp_clone_pdu( pdu );
676
                asp->pdu->variables = pdu->variables;
677
                pdu->variables = NULL;
678
            }
679
            else {
680
                /* discard outstanding requests */
681
                for ( req_p = asp->outstanding_requests ;
682
                        req_p != NULL ; req_p = next_req ) {
683
 
684
                        next_req = req_p->next_request;
685
                        free( req_p );
686
                }
687
                asp->outstanding_requests = NULL;
688
            }
689
        }
690
        return status;
691
}
692
 
693
 
694
int
695
handle_var_list(struct agent_snmp_session  *asp)
696
{
697
    struct variable_list *varbind_ptr;
698
    u_char  statType;
699
    u_char *statP;
700
    size_t  statLen;
701
    u_short acl;
702
    WriteMethod *write_method;
703
    AddVarMethod *add_method;
704
    int     noSuchObject = TRUE;
705
    int     count, view;
706
 
707
    count = 0;
708
    varbind_ptr = asp->start;
709
    if ( !varbind_ptr ) {
710
        return SNMP_ERR_NOERROR;
711
    }
712
 
713
    while (1) {
714
 
715
        count++;
716
statp_loop:
717
        statP = getStatPtr(  varbind_ptr->name,
718
                           &varbind_ptr->name_length,
719
                           &statType, &statLen, &acl,
720
                           asp->exact, &write_method, asp->pdu, &noSuchObject);
721
 
722
        if (statP == NULL && (asp->rw != WRITE || write_method == NULL)) {
723
                /*  Careful -- if the varbind was lengthy, it will have
724
                    allocated some memory.  */
725
                snmp_set_var_value(varbind_ptr, NULL, 0);
726
                varbind_ptr->val.integer   = NULL;
727
                varbind_ptr->val_len = 0;
728
                if ( asp->exact ) {
729
                    if ( noSuchObject == TRUE ){
730
                        statType = SNMP_NOSUCHOBJECT;
731
                    } else {
732
                        statType = SNMP_NOSUCHINSTANCE;
733
                    }
734
                } else {
735
                    statType = SNMP_ENDOFMIBVIEW;
736
                }
737
                if (asp->pdu->version == SNMP_VERSION_1) {
738
                    asp->pdu->errstat = SNMP_ERR_NOSUCHNAME;
739
                    asp->pdu->errindex = count;
740
                    return SNMP_ERR_NOSUCHNAME;
741
                }
742
                else if (asp->rw == WRITE) {
743
                    asp->pdu->errstat =
744
                        ( noSuchObject  ? SNMP_ERR_NOTWRITABLE
745
                                        : SNMP_ERR_NOCREATION );
746
                    asp->pdu->errindex = count;
747
                    return asp->pdu->errstat;
748
                }
749
                else
750
                    varbind_ptr->type = statType;
751
        }
752
                /* Delegated variables should be added to the
753
                   relevant outgoing request */
754
        else if ( IS_DELEGATED(statType)) {
755
                add_method = (AddVarMethod*)statP;
756
                statType = (*add_method)( asp, varbind_ptr );
757
        }
758
                /* GETNEXT/GETBULK should just skip inaccessible entries */
759
        else if ((view = in_a_view(varbind_ptr->name, &varbind_ptr->name_length,
760
                                   asp->pdu, varbind_ptr->type))
761
                         && !asp->exact) {
762
                if (view != 5) send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
763
                goto statp_loop;
764
        }
765
                /* Other access problems are permanent */
766
        else if (( asp->rw == WRITE && !(acl & 2)) || view) {
767
            if (asp->pdu->version == SNMP_VERSION_1 || asp->rw != WRITE) {
768
                if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE))
769
                  DEBUGMSGTL(("snmp_agent", "    >> noSuchName (read-only)\n"));
770
                ERROR_MSG("read-only");
771
                statType = SNMP_ERR_NOSUCHNAME;
772
            }
773
            else {
774
                if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE))
775
                  DEBUGMSGTL(("snmp_agent", "    >> notWritable\n"));
776
                ERROR_MSG("Not Writable");
777
                statType = SNMP_ERR_NOTWRITABLE;
778
            }
779
            asp->pdu->errstat = statType;
780
            asp->pdu->errindex = count;
781
            send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
782
            return statType;
783
        }
784
        else {
785
            /* dump verbose info */
786
            if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE) && statP)
787
                dump_var(varbind_ptr->name, varbind_ptr->name_length,
788
                                statType, statP, statLen);
789
 
790
                /*  FINALLY we can act on SET requests ....*/
791
            if ( asp->rw == WRITE ) {
792
                if ( write_method != NULL ) {
793
                    statType = (*write_method)(asp->mode,
794
                                               varbind_ptr->val.string,
795
                                               varbind_ptr->type,
796
                                               varbind_ptr->val_len, statP,
797
                                               varbind_ptr->name,
798
                                               varbind_ptr->name_length);
799
                    if (statType != SNMP_ERR_NOERROR) {
800
                      asp->pdu->errstat = statType;
801
                      asp->pdu->errindex = count;
802
                      return statType;
803
                    }
804
                }
805
                else {
806
                    if (!goodValue(varbind_ptr->type, varbind_ptr->val_len,
807
                                    statType, statLen)){
808
                        if (asp->pdu->version == SNMP_VERSION_1)
809
                            statType = SNMP_ERR_BADVALUE;
810
                        else
811
                            statType = SNMP_ERR_WRONGTYPE; /* poor approximation */
812
                        asp->pdu->errstat = statType;
813
                        asp->pdu->errindex = count;
814
                        return statType;
815
                    }
816
                    /* actually do the set if necessary */
817
                    if (asp->mode == COMMIT)
818
                        setVariable(varbind_ptr->val.string, varbind_ptr->type,
819
                                    varbind_ptr->val_len, statP, statLen);
820
                }
821
            }
822
                /* ... or save the results from assorted GETs */
823
            else {
824
                     snmp_set_var_value(varbind_ptr, statP, statLen);
825
                     varbind_ptr->type = statType;
826
            }
827
        }
828
 
829
        if ( varbind_ptr == asp->end )
830
             return SNMP_ERR_NOERROR;
831
        varbind_ptr = varbind_ptr->next_variable;
832
        if ( asp->mode == RESERVE1 )
833
            snmp_vars_inc++;
834
    }
835
}
836
 
837
 
838
 
839
static int
840
goodValue(u_char inType,
841
          size_t inLen,
842
          u_char actualType,
843
          size_t actualLen)
844
{
845
    if (inLen > actualLen)
846
        return FALSE;
847
    return (inType == actualType);
848
}
849
 
850
static void
851
setVariable(u_char *var_val,
852
            u_char var_val_type,
853
            size_t var_val_len,
854
            u_char *statP,
855
            size_t statLen)
856
{
857
    size_t buffersize = 1000;
858
 
859
    switch(var_val_type){
860
        case ASN_INTEGER:
861
            asn_parse_int(var_val, &buffersize, &var_val_type, (long *)statP, statLen);
862
            break;
863
        case ASN_COUNTER:
864
        case ASN_GAUGE:
865
        case ASN_TIMETICKS:
866
            asn_parse_unsigned_int(var_val, &buffersize, &var_val_type, (u_long *)statP, statLen);
867
            break;
868
        case ASN_COUNTER64:
869
            asn_parse_unsigned_int64(var_val, &buffersize, &var_val_type,
870
                                     (struct counter64 *)statP, statLen);
871
            break;
872
        case ASN_OCTET_STR:
873
        case ASN_IPADDRESS:
874
        case ASN_OPAQUE:
875
        case ASN_NSAP:
876
            asn_parse_string(var_val, &buffersize, &var_val_type, statP, &statLen);
877
            break;
878
        case ASN_OBJECT_ID:
879
            asn_parse_objid(var_val, &buffersize, &var_val_type, (oid *)statP, &statLen);
880
            break;
881
        case ASN_BIT_STR:
882
            asn_parse_bitstring(var_val, &buffersize, &var_val_type, statP, &statLen);
883
            break;
884
    }
885
}

powered by: WebSVN 2.1.0

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