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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [net/] [snmp/] [agent/] [v2_0/] [src/] [snmp_agent.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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