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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [snmp/] [lib/] [v2_0/] [src/] [snmp_client.c] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      ./lib/current/src/snmp_client.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_client.c - a toolkit of common functions for an SNMP client.
94
 *
95
 */
96
/**********************************************************************
97
        Copyright 1988, 1989, 1991, 1992 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 <stdio.h>
121
#include <errno.h>
122
#if HAVE_STDLIB_H
123
#include <stdlib.h>
124
#endif
125
#if HAVE_STRING_H
126
#include <string.h>
127
#else
128
#include <strings.h>
129
#endif
130
#if HAVE_UNISTD_H
131
#include <unistd.h>
132
#endif
133
#include <sys/types.h>
134
#if TIME_WITH_SYS_TIME
135
# ifdef WIN32
136
#  include <sys/timeb.h>
137
# else
138
#  include <sys/time.h>
139
# endif
140
# include <time.h>
141
#else
142
# if HAVE_SYS_TIME_H
143
#  include <sys/time.h>
144
# else
145
#  include <time.h>
146
# endif
147
#endif
148
#if HAVE_SYS_PARAM_H
149
#include <sys/param.h>
150
#endif
151
#if HAVE_NETINET_IN_H
152
#include <netinet/in.h>
153
#endif
154
#if HAVE_ARPA_INET_H
155
#include <arpa/inet.h>
156
#endif
157
#if HAVE_SYS_SELECT_H
158
#include <sys/select.h>
159
#endif
160
 
161
#if HAVE_DMALLOC_H
162
#include <dmalloc.h>
163
#endif
164
 
165
#if HAVE_WINSOCK_H
166
#include <winsock.h>
167
#endif
168
 
169
#include "asn1.h"
170
#include "snmp.h"
171
#include "snmp_api.h"
172
#include "snmp_impl.h"
173
#include "snmp_client.h"
174
#include "mib.h"
175
 
176
 
177
#ifndef BSD4_3
178
#define BSD4_2
179
#endif
180
 
181
#ifndef FD_SET
182
 
183
typedef long    fd_mask;
184
#define NFDBITS (sizeof(fd_mask) * NBBY)        /* bits per mask */
185
 
186
#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
187
#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
188
#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
189
#define FD_ZERO(p)      memset((p), 0, sizeof(*(p)))
190
#endif
191
 
192
#define PARTY_MIB_BASE   ".1.3.6.1.6.3.3.1.3.127.0.0.1.1"
193
#define CONTEXT_MIB_BASE ".1.3.6.1.6.3.3.1.4.127.0.0.1.1"
194
 
195
 
196
struct snmp_pdu *
197
snmp_pdu_create(int command)
198
{
199
    struct snmp_pdu *pdu;
200
    struct sockaddr_in *pduIp;
201
 
202
    pdu = (struct snmp_pdu *)calloc(1,sizeof(struct snmp_pdu));
203
    if (pdu) {
204
    pduIp = (struct sockaddr_in *)&(pdu->address);
205
    pdu->version                 = SNMP_DEFAULT_VERSION;
206
    pdu->command                 = command;
207
    pdu->errstat                 = SNMP_DEFAULT_ERRSTAT;
208
    pdu->errindex                = SNMP_DEFAULT_ERRINDEX;
209
    pduIp->sin_addr.s_addr       = SNMP_DEFAULT_ADDRESS;
210
    pdu->securityNameLen         = 0;
211
    pdu->contextNameLen          = 0;
212
    pdu->reqid                   = snmp_get_next_reqid();
213
    pdu->msgid                   = snmp_get_next_msgid();
214
    }
215
    return pdu;
216
 
217
}
218
 
219
 
220
/*
221
 * Add a null variable with the requested name to the end of the list of
222
 * variables for this pdu.
223
 */
224
struct variable_list* snmp_add_null_var(struct snmp_pdu * pdu,
225
                                        oid *name,
226
                                        size_t name_length)
227
{
228
    return snmp_pdu_add_variable(pdu, name, name_length, ASN_NULL, NULL, 0);
229
}
230
 
231
 
232
 
233
int
234
snmp_synch_input(int op,
235
                 struct snmp_session *session,
236
                 int reqid,
237
                 struct snmp_pdu *pdu,
238
                 void *magic)
239
{
240
    struct synch_state *state = (struct synch_state *)magic;
241
    int rpt_type;
242
 
243
    if (reqid != state->reqid && pdu->command != SNMP_MSG_REPORT)
244
        return 0;
245
 
246
    state->waiting = 0;
247
    if (op == RECEIVED_MESSAGE) {
248
      if (pdu->command == SNMP_MSG_REPORT) {
249
#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
250
        rpt_type = snmpv3_get_report_type(pdu);
251
        if (SNMPV3_IGNORE_UNAUTH_REPORTS ||
252
            rpt_type == SNMPERR_NOT_IN_TIME_WINDOW)
253
          state->waiting = 1;
254
        session->s_snmp_errno = rpt_type;
255
#else
256
        session->s_snmp_errno = SNMPERR_UNSUPPORTED_SEC_LEVEL;
257
#endif
258
        state->pdu = NULL;
259
        state->status = STAT_ERROR;
260
        SET_SNMP_ERROR(rpt_type);
261
      } else if (pdu->command == SNMP_MSG_RESPONSE) {
262
        /* clone the pdu to return to snmp_synch_response */
263
        state->pdu = snmp_clone_pdu(pdu);
264
        state->status = STAT_SUCCESS;
265
        session->s_snmp_errno = SNMPERR_SUCCESS;
266
      }
267
    } else if (op == TIMED_OUT){
268
        state->pdu               = NULL;
269
        state->status            = STAT_TIMEOUT;
270
        session->s_snmp_errno    = SNMPERR_TIMEOUT;
271
        SET_SNMP_ERROR(SNMPERR_TIMEOUT);
272
    }
273
 
274
    return 1;
275
}
276
 
277
 
278
/*
279
 * Clone an SNMP variable data structure.
280
 * Sets pointers to structure private storage, or
281
 * allocates larger object identifiers and values as needed.
282
 *
283
 * Caller must make list association for cloned variable.
284
 *
285
 * Returns 0 if successful.
286
 */
287
int
288
snmp_clone_var(struct variable_list *var, struct variable_list *newvar)
289
{
290
    if (!newvar || !var) return 1;
291
 
292
    memmove(newvar, var, sizeof(struct variable_list));
293
    newvar->next_variable = 0; newvar->name = 0; newvar->val.string = 0;
294
 
295
    /*
296
     * Clone the object identifier and the value.
297
     * Allocate memory iff original will not fit into local storage.
298
     */
299
    if (snmp_set_var_objid(newvar, var->name, var->name_length))
300
        return 1;
301
 
302
    /* need a pointer and a length to copy a string value. */
303
    if (var->val.string && var->val_len) {
304
      if (var->val.string != &var->buf[0]){
305
        if (var->val_len <= sizeof(var->buf))
306
            newvar->val.string = newvar->buf;
307
        else {
308
            newvar->val.string = (u_char *)malloc(var->val_len);
309
            if (!newvar->val.string) return 1;
310
        }
311
        memmove(newvar->val.string, var->val.string, var->val_len);
312
      }
313
      else { /* fix the pointer to new local store */
314
        newvar->val.string = newvar->buf;
315
      }
316
    }
317
    else {
318
        newvar->val.string = 0; newvar->val_len = 0;
319
    }
320
 
321
    return 0;
322
}
323
 
324
 
325
/*
326
 * Possibly make a copy of source memory buffer.
327
 * Will reset destination pointer if source pointer is NULL.
328
 * Returns 0 if successful, 1 if memory allocation fails.
329
 */
330
int
331
snmp_clone_mem(void ** dstPtr, void * srcPtr, unsigned len)
332
{
333
    *dstPtr = 0;
334
    if (srcPtr){
335
        *dstPtr = malloc(len + 1);
336
        if (! *dstPtr){
337
            return 1;
338
        }
339
        memmove(*dstPtr, srcPtr, len);
340
        /* this is for those routines that expect 0-terminated strings!!!
341
           someone should rather have called strdup
342
        */
343
        ((char *)*dstPtr)[len] = 0;
344
    }
345
    return 0;
346
}
347
 
348
 
349
/*
350
 * Creates and allocates a clone of the input PDU,
351
 * but does NOT copy the variables.
352
 * This function should be used with another function,
353
 * such as _copy_pdu_vars.
354
 *
355
 * Returns a pointer to the cloned PDU if successful.
356
 * Returns 0 if failure.
357
 */
358
static
359
struct snmp_pdu *
360
_clone_pdu_header(struct snmp_pdu *pdu)
361
{
362
    struct snmp_pdu *newpdu;
363
 
364
    newpdu = (struct snmp_pdu *)malloc(sizeof(struct snmp_pdu));
365
    if (!newpdu) return 0;
366
    memmove(newpdu, pdu, sizeof(struct snmp_pdu));
367
 
368
    /* reset copied pointers if copy fails */
369
    newpdu->variables = 0; newpdu->enterprise = 0; newpdu->community = 0;
370
    newpdu->securityEngineID = 0; newpdu->securityName = 0;
371
    newpdu->contextEngineID  = 0; newpdu->contextName  = 0;
372
 
373
    /* copy buffers individually. If any copy fails, all are freed. */
374
    if ( snmp_clone_mem((void **)&newpdu->enterprise, pdu->enterprise,
375
                                    sizeof(oid)*pdu->enterprise_length)
376
     ||  snmp_clone_mem((void **)&newpdu->community, pdu->community,
377
                                    pdu->community_len)
378
#ifdef SNMPERR_UNSUPPORTED_SEC_LEVEL
379
     ||  snmp_clone_mem((void **)&newpdu->contextEngineID, pdu->contextEngineID,
380
                                    pdu->contextEngineIDLen)
381
     ||  snmp_clone_mem((void **)&newpdu->securityEngineID, pdu->securityEngineID,
382
                                    pdu->securityEngineIDLen)
383
     ||  snmp_clone_mem((void **)&newpdu->contextName, pdu->contextName,
384
                                    pdu->contextNameLen)
385
     ||  snmp_clone_mem((void **)&newpdu->securityName, pdu->securityName,
386
                                    pdu->securityNameLen)
387
#endif
388
       )
389
    {
390
        snmp_free_pdu(newpdu); return 0;
391
    }
392
    return newpdu;
393
}
394
 
395
 
396
/*
397
 * Copy some or all variables from source PDU to target PDU.
398
 * This function consolidates many of the needs of PDU variables:
399
 * Clone PDU : copy all the variables.
400
 * Split PDU : skip over some variables to copy other variables.
401
 * Fix PDU   : remove variable associated with error index.
402
 *
403
 * Designed to work with _clone_pdu_header.
404
 *
405
 * If drop_err is set, drop any variable associated with errindex.
406
 * If skip_count is set, skip the number of variable in pdu's list.
407
 * While copy_count is greater than zero, copy pdu variables to newpdu.
408
 *
409
 * If an error occurs, newpdu is freed and pointer is set to 0.
410
 *
411
 * Returns a pointer to the cloned PDU if successful.
412
 * Returns 0 if failure.
413
 */
414
static
415
struct snmp_pdu *
416
_copy_pdu_vars(struct snmp_pdu *pdu,  /* source PDU */
417
        struct snmp_pdu *newpdu,      /* target PDU */
418
        int drop_err,                 /* !=0 drop errored variable */
419
        int skip_count,               /* !=0 number of variables to skip */
420
        int copy_count)               /* !=0 number of variables to copy */
421
{
422
    struct variable_list *var, *newvar, *oldvar;
423
    int ii, copied;
424
 
425
    if (!newpdu) return 0;            /* where is PDU to copy to ? */
426
 
427
    var = pdu->variables;
428
    while (var && (skip_count-- > 0)) /* skip over pdu variables */
429
        var = var->next_variable;
430
 
431
    oldvar = 0; ii = 0; copied = 0;
432
    if (pdu->flags & UCD_MSG_FLAG_FORCE_PDU_COPY)
433
        copied = 1;     /* We're interested in 'empty' responses too */
434
    while (var && (copy_count-- > 0))
435
    {
436
        /* errindex starts from 1. If drop_err, skip the errored variable */
437
        if (drop_err && (++ii == pdu->errindex)) {
438
            var = var->next_variable; continue;
439
        }
440
 
441
        /* clone the next variable. Cleanup if alloc fails */
442
        newvar = (struct variable_list *)malloc(sizeof(struct variable_list));
443
        if (snmp_clone_var(var, newvar)){
444
            if (newvar) free((char *)newvar);
445
            snmp_free_pdu(newpdu); return 0;
446
        }
447
        copied++;
448
 
449
        /* add cloned variable to new PDU */
450
        if (0 == newpdu->variables) newpdu->variables = newvar;
451
        if (oldvar) oldvar->next_variable = newvar;
452
        oldvar = newvar;
453
 
454
        var = var->next_variable;
455
    }
456
    /* Error if bad errindex or if target PDU has no variables copied */
457
    if ((drop_err && (ii < pdu->errindex))
458
#if TEMPORARILY_DISABLED
459
                /* SNMPv3 engineID probes are allowed to be empty.
460
                   See the comment in snmp_api.c for further details */
461
        || copied == 0
462
#endif
463
      ) {
464
        snmp_free_pdu(newpdu); return 0;
465
    }
466
    return newpdu;
467
}
468
 
469
 
470
/*
471
 * Creates (allocates and copies) a clone of the input PDU.
472
 * If drop_err is set, don't copy any variable associated with errindex.
473
 * This function is called by snmp_clone_pdu and snmp_fix_pdu.
474
 *
475
 * Returns a pointer to the cloned PDU if successful.
476
 * Returns 0 if failure.
477
 */
478
static
479
struct snmp_pdu *
480
_clone_pdu(struct snmp_pdu *pdu, int drop_err)
481
{
482
    struct snmp_pdu *newpdu;
483
    newpdu = _clone_pdu_header(pdu);
484
    newpdu = _copy_pdu_vars(pdu, newpdu,
485
            drop_err,
486
            0, 10000);  /* skip none, copy all */
487
 
488
    return newpdu;
489
}
490
 
491
 
492
/*
493
 * This function will clone a PDU including all of its variables.
494
 *
495
 * Returns a pointer to the cloned PDU if successful.
496
 * Returns 0 if failure
497
 */
498
struct snmp_pdu *
499
snmp_clone_pdu(struct snmp_pdu *pdu)
500
{
501
    return _clone_pdu(pdu, 0); /* copies all variables */
502
}
503
 
504
 
505
/*
506
 * This function will clone a PDU including some of its variables.
507
 *
508
 * If skip_count is not zero, it defines the number of variables to skip.
509
 * If copy_count is not zero, it defines the number of variables to copy.
510
 *
511
 * Returns a pointer to the cloned PDU if successful.
512
 * Returns 0 if failure.
513
 */
514
struct snmp_pdu *
515
snmp_split_pdu(struct snmp_pdu *pdu, int skip_count, int copy_count)
516
{
517
    struct snmp_pdu *newpdu;
518
    newpdu = _clone_pdu_header(pdu);
519
    newpdu = _copy_pdu_vars(pdu, newpdu,
520
            0,         /* don't drop any variables */
521
            skip_count,
522
            copy_count);
523
 
524
    return newpdu;
525
}
526
 
527
 
528
/*
529
 * If there was an error in the input pdu, creates a clone of the pdu
530
 * that includes all the variables except the one marked by the errindex.
531
 * The command is set to the input command and the reqid, errstat, and
532
 * errindex are set to default values.
533
 * If the error status didn't indicate an error, the error index didn't
534
 * indicate a variable, the pdu wasn't a get response message, or there
535
 * would be no remaining variables, this function will return 0.
536
 * If everything was successful, a pointer to the fixed cloned pdu will
537
 * be returned.
538
 */
539
struct snmp_pdu *
540
snmp_fix_pdu(struct snmp_pdu *pdu, int command)
541
{
542
    struct snmp_pdu *newpdu;
543
 
544
    if ((pdu->command != SNMP_MSG_RESPONSE)
545
     || (pdu->errstat == SNMP_ERR_NOERROR)
546
     || (0 == pdu->variables)
547
     || (pdu->errindex <= 0))
548
    {
549
            return 0; /* pre-condition tests fail */
550
    }
551
 
552
    newpdu = _clone_pdu(pdu, 1); /* copies all except errored variable */
553
    if (!newpdu)
554
        return 0;
555
    if (!newpdu->variables) {
556
        snmp_free_pdu(newpdu);
557
        return 0; /* no variables. "should not happen" */
558
    }
559
    newpdu->command = command;
560
    newpdu->reqid = snmp_get_next_reqid();
561
    newpdu->msgid = snmp_get_next_msgid();
562
    newpdu->errstat = SNMP_DEFAULT_ERRSTAT;
563
    newpdu->errindex = SNMP_DEFAULT_ERRINDEX;
564
 
565
    return newpdu;
566
}
567
 
568
 
569
/*
570
 * Returns the number of variables bound to a PDU structure
571
 */
572
unsigned long
573
snmp_varbind_len(struct snmp_pdu * pdu)
574
{
575
    register struct variable_list *vars;
576
    unsigned long retVal = 0;
577
    if (pdu)
578
      for (vars = pdu->variables; vars; vars = vars->next_variable)
579
      {
580
        retVal++;
581
      }
582
 
583
    return retVal;
584
}
585
 
586
/*
587
 * Add object identifier name to SNMP variable.
588
 * If the name is large, additional memory is allocated.
589
 * Returns 0 if successful.
590
 */
591
 
592
int
593
snmp_set_var_objid (struct variable_list *vp,
594
                    const oid *objid, size_t name_length)
595
{
596
    size_t len = sizeof(oid) * name_length;
597
 
598
    /* use built-in storage for smaller values */
599
    if (len <= sizeof(vp->name_loc)) {
600
        vp->name = vp->name_loc;
601
    }
602
    else {
603
        vp->name = (oid *)malloc(len);
604
        if (!vp->name) return 1;
605
    }
606
    memmove(vp->name, objid, len);
607
    vp->name_length = name_length;
608
    return 0;
609
}
610
 
611
/*
612
 * Add some value to SNMP variable.
613
 * If the value is large, additional memory is allocated.
614
 * Returns 0 if successful.
615
 */
616
 
617
int
618
snmp_set_var_value(struct variable_list *newvar,
619
                    u_char *val_str, size_t val_len)
620
{
621
    if (newvar->val.string &&
622
        newvar->val.string != newvar->buf)
623
    {
624
        free(newvar->val.string);
625
    }
626
 
627
    newvar->val.string = 0; newvar->val_len = 0;
628
 
629
    /* need a pointer and a length to copy a string value. */
630
    if (val_str && val_len)
631
    {
632
        if (val_len <= sizeof(newvar->buf))
633
            newvar->val.string = newvar->buf;
634
        else {
635
            newvar->val.string = (u_char *)malloc(val_len);
636
            if (!newvar->val.string) return 1;
637
        }
638
        memmove(newvar->val.string, val_str, val_len);
639
        newvar->val_len = val_len;
640
    }
641
 
642
    return 0;
643
}
644
 
645
 
646
int
647
snmp_synch_response_cb(struct snmp_session *ss,
648
                    struct snmp_pdu *pdu,
649
                    struct snmp_pdu **response,
650
                    snmp_callback pcb)
651
{
652
    struct synch_state lstate, *state;
653
    snmp_callback cbsav;
654
    void * cbmagsav;
655
    int numfds, count;
656
    fd_set fdset;
657
    struct timeval timeout, *tvp;
658
    int block;
659
 
660
    memset((void *)&lstate, 0, sizeof(lstate));
661
    state = &lstate;
662
    cbsav = ss->callback;
663
    cbmagsav = ss->callback_magic;
664
    ss->callback = pcb;
665
    ss->callback_magic = (void *)state;
666
 
667
    if ((state->reqid = snmp_send(ss, pdu)) == 0){
668
        snmp_free_pdu(pdu);
669
        state->status = STAT_ERROR;
670
    }
671
    else
672
        state->waiting = 1;
673
 
674
    while(state->waiting){
675
        numfds = 0;
676
        FD_ZERO(&fdset);
677
        block = SNMPBLOCK;
678
        tvp = &timeout;
679
        timerclear(tvp);
680
        snmp_select_info(&numfds, &fdset, tvp, &block);
681
        if (block == 1)
682
            tvp = NULL; /* block without timeout */
683
        count = select(numfds, &fdset, 0, 0, tvp);
684
        if (count > 0){
685
            snmp_read(&fdset);
686
        } else switch(count){
687
            case 0:
688
                snmp_timeout();
689
                break;
690
            case -1:
691
                if (errno == EINTR){
692
                    continue;
693
                } else {
694
                    snmp_errno = SNMPERR_GENERR;
695
                /* CAUTION! if another thread closed the socket(s)
696
                   waited on here, the session structure was freed.
697
                   It would be nice, but we can't rely on the pointer.
698
                    ss->s_snmp_errno = SNMPERR_GENERR;
699
                    ss->s_errno = errno;
700
                 */
701
                    snmp_set_detail(strerror(errno));
702
                }
703
            /* FALLTHRU */
704
            default:
705
                state->status = STAT_ERROR;
706
                state->waiting = 0;
707
        }
708
    }
709
    *response = state->pdu;
710
    ss->callback = cbsav;
711
    ss->callback_magic = cbmagsav;
712
    return state->status;
713
}
714
 
715
int
716
snmp_synch_response(struct snmp_session *ss,
717
                    struct snmp_pdu *pdu,
718
                    struct snmp_pdu **response)
719
{
720
    return snmp_synch_response_cb(ss,pdu,response,snmp_synch_input);
721
}
722
 
723
int
724
snmp_sess_synch_response(void *sessp,
725
                         struct snmp_pdu *pdu,
726
                         struct snmp_pdu **response)
727
{
728
    struct snmp_session *ss;
729
    struct synch_state lstate, *state;
730
    snmp_callback cbsav;
731
    void * cbmagsav;
732
    int numfds, count;
733
    fd_set fdset;
734
    struct timeval timeout, *tvp;
735
    int block;
736
 
737
    ss = snmp_sess_session(sessp);
738
    memset((void *)&lstate, 0, sizeof(lstate));
739
    state = &lstate;
740
    cbsav = ss->callback;
741
    cbmagsav = ss->callback_magic;
742
    ss->callback = snmp_synch_input;
743
    ss->callback_magic = (void *)state;
744
 
745
    if ((state->reqid = snmp_sess_send(sessp, pdu)) == 0){
746
        snmp_free_pdu(pdu);
747
        state->status = STAT_ERROR;
748
    }
749
    else
750
        state->waiting = 1;
751
 
752
    while(state->waiting){
753
        numfds = 0;
754
        FD_ZERO(&fdset);
755
        block = SNMPBLOCK;
756
        tvp = &timeout;
757
        timerclear(tvp);
758
        snmp_sess_select_info(sessp, &numfds, &fdset, tvp, &block);
759
        if (block == 1)
760
            tvp = NULL; /* block without timeout */
761
        count = select(numfds, &fdset, 0, 0, tvp);
762
        if (count > 0){
763
            snmp_sess_read(sessp, &fdset);
764
        } else switch(count){
765
            case 0:
766
                snmp_sess_timeout(sessp);
767
                break;
768
            case -1:
769
                if (errno == EINTR){
770
                    continue;
771
                } else {
772
                    snmp_errno = SNMPERR_GENERR;
773
                /* CAUTION! if another thread closed the socket(s)
774
                   waited on here, the session structure was freed.
775
                   It would be nice, but we can't rely on the pointer.
776
                    ss->s_snmp_errno = SNMPERR_GENERR;
777
                    ss->s_errno = errno;
778
                 */
779
                    snmp_set_detail(strerror(errno));
780
                }
781
            /* FALLTHRU */
782
            default:
783
                state->status = STAT_ERROR;
784
                state->waiting = 0;
785
        }
786
    }
787
    *response = state->pdu;
788
    ss->callback = cbsav;
789
    ss->callback_magic = cbmagsav;
790
    return state->status;
791
}
792
 
793
 
794
const char *error_string[19] = {
795
    "(noError) No Error",
796
    "(tooBig) Response message would have been too large.",
797
    "(noSuchName) There is no such variable name in this MIB.",
798
    "(badValue) The value given has the wrong type or length.",
799
    "(readOnly) The two parties used do not have access to use the specified SNMP PDU.",
800
    "(genError) A general failure occured",
801
    "noAccess",
802
    "wrongType",
803
    "wrongLength",
804
    "wrongEncoding",
805
    "wrongValue",
806
    "noCreation",
807
    "inconsistentValue",
808
    "resourceUnavailable",
809
    "commitFailed",
810
    "undoFailed",
811
    "authorizationError",
812
    "notWritable",
813
    "inconsistentName"
814
};
815
 
816
const char *
817
snmp_errstring(int errstat)
818
{
819
    if (errstat <= MAX_SNMP_ERR && errstat >= SNMP_ERR_NOERROR){
820
        return error_string[errstat];
821
    } else {
822
        return "Unknown Error";
823
    }
824
}

powered by: WebSVN 2.1.0

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