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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1254 phoenix
//==========================================================================
2
//
3
//      ./agent/current/src/snmpd.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
 * snmpd.c - rrespond to SNMP queries from management stations
94
 *
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
#include <config.h>
118
 
119
#include <stdio.h>
120
#include <errno.h>
121
#if HAVE_STRING_H
122
#include <string.h>
123
#else
124
#include <strings.h>
125
#endif
126
#if HAVE_STDLIB_H
127
#include <stdlib.h>
128
#endif
129
#if HAVE_UNISTD_H
130
#include <unistd.h>
131
#endif
132
#include <sys/types.h>
133
#if HAVE_NETINET_IN_H
134
#include <netinet/in.h>
135
#endif
136
#if HAVE_ARPA_INET_H
137
#include <arpa/inet.h>
138
#endif
139
#if TIME_WITH_SYS_TIME
140
# ifdef WIN32
141
#  include <sys/timeb.h>
142
# else
143
#  include <sys/time.h>
144
# endif
145
# include <time.h>
146
#else
147
# if HAVE_SYS_TIME_H
148
#  include <sys/time.h>
149
# else
150
#  include <time.h>
151
# endif
152
#endif
153
#if HAVE_SYS_SELECT_H
154
#include <sys/select.h>
155
#endif
156
#if HAVE_SYS_SOCKET_H
157
#include <sys/socket.h>
158
#elif HAVE_WINSOCK_H
159
#include <winsock.h>
160
#endif
161
#if HAVE_NET_IF_H
162
#include <net/if.h>
163
#endif
164
#if HAVE_INET_MIB2_H
165
#include <inet/mib2.h>
166
#endif
167
#if HAVE_SYS_IOCTL_H
168
#include <sys/ioctl.h>
169
#endif
170
#if HAVE_SYS_FILE_H
171
#include <sys/file.h>
172
#endif
173
#if HAVE_FCNTL_H
174
#include <fcntl.h>
175
#endif
176
#if HAVE_SYS_WAIT_H
177
#include <sys/wait.h>
178
#endif
179
#include <signal.h>
180
#ifdef HAVE_SYS_PARAM_H
181
#include <sys/param.h>
182
#endif
183
 
184
#ifndef FD_SET
185
typedef long    fd_mask;
186
#define NFDBITS (sizeof(fd_mask) * NBBY)        /* bits per mask */
187
#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
188
#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
189
#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
190
#define FD_ZERO(p)      memset((p), 0, sizeof(*(p)))
191
#endif
192
 
193
#if HAVE_DMALLOC_H
194
#include <dmalloc.h>
195
#endif
196
 
197
#include "asn1.h"
198
#include "snmp_api.h"
199
#include "snmp_impl.h"
200
#include "system.h"
201
#include "read_config.h"
202
#include "snmp.h"
203
#include "mib.h"
204
#include "m2m.h"
205
#include "snmp_vars.h"
206
#include "agent_read_config.h"
207
#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
208
#include "snmpv3.h"
209
#endif
210
#include "callback.h"
211
#include "snmp_alarm.h"
212
#include "default_store.h"
213
#include "mib_module_config.h"
214
 
215
#include "snmp_client.h"
216
#include "snmpd.h"
217
#include "var_struct.h"
218
#include "mibgroup/struct.h"
219
#include "mibgroup/util_funcs.h"
220
#include "snmp_debug.h"
221
#include "mib_modules.h"
222
 
223
#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
224
#include "snmpusm.h"
225
#endif
226
#include "tools.h"
227
#include "lcd_time.h"
228
 
229
#include "transform_oids.h"
230
 
231
#include "snmp_agent.h"
232
#include "agent_trap.h"
233
#include "ds_agent.h"
234
#include "agent_read_config.h"
235
#include "snmp_logging.h"
236
 
237
#include "version.h"
238
 
239
#include "mib_module_includes.h"
240
 
241
/*
242
 * Globals.
243
 */
244
#ifdef USE_LIBWRAP
245
#include <tcpd.h>
246
 
247
int allow_severity       = LOG_INFO;
248
int deny_severity        = LOG_WARNING;
249
#endif  /* USE_LIBWRAP */
250
 
251
#define TIMETICK         500000L
252
#define ONE_SEC         1000000L
253
 
254
static int      log_addresses    = 0;
255
int             snmp_dump_packet;
256
static int      running          = 1;
257
static int      reconfig         = 0;
258
 
259
struct addrCache {
260
    in_addr_t   addr;
261
    int         status;
262
#define UNUSED  0
263
#define USED    1
264
#define OLD     2
265
};
266
 
267
#define ADDRCACHE 10
268
 
269
static struct addrCache addrCache[ADDRCACHE];
270
static int              lastAddrAge = 0;
271
 
272
extern char **argvrestartp;
273
extern char  *argvrestart;
274
extern char  *argvrestartname;
275
 
276
#define NUM_SOCKETS     32
277
 
278
#ifdef USING_SMUX_MODULE
279
static int sdlist[NUM_SOCKETS], sdlen = 0;
280
int smux_listen_sd;
281
#endif /* USING_SMUX_MODULE */
282
 
283
/*
284
 * Prototypes.
285
 */
286
int snmp_read_packet (int);
287
int snmp_input (int, struct snmp_session *, int, struct snmp_pdu *, void *);
288
int main (int, char **);
289
static void SnmpTrapNodeDown (void);
290
static int receive(void);
291
int snmp_check_packet(struct snmp_session*, snmp_ipaddr);
292
int snmp_check_parse(struct snmp_session*, struct snmp_pdu*, int);
293
 
294
#if !defined(__ECOS)
295
static void usage(char *prog)
296
{
297
        printf("\nUsage:  %s [-h] [-v] [-f] [-a] [-d] [-V] [-P PIDFILE] [-q] [-D] [-p NUM] [-L] [-l LOGFILE] [-r]",prog);
298
#if HAVE_UNISTD_H
299
        printf(" [-u uid] [-g gid]");
300
#endif
301
        printf("\n");
302
        printf("\n\tVersion:  %s\n",VersionInfo);
303
        printf("\tAuthor:   Wes Hardaker\n");
304
        printf("\tEmail:    ucd-snmp-coders@ucd-snmp.ucdavis.edu\n");
305
        printf("\n-h\t\tThis usage message.\n");
306
        printf("-H\t\tDisplay configuration file directives understood.\n");
307
        printf("-v\t\tVersion information.\n");
308
        printf("-f\t\tDon't fork from the shell.\n");
309
        printf("-a\t\tLog addresses.\n");
310
        printf("-d\t\tDump sent and received UDP SNMP packets\n");
311
        printf("-V\t\tVerbose display\n");
312
        printf("-P PIDFILE\tUse PIDFILE to store process id\n");
313
        printf("-q\t\tPrint information in a more parsable format (quick-print)\n");
314
        printf("-D\t\tTurn on debugging output\n");
315
        printf("-p NUM\t\tRun on port NUM instead of the default:  161\n");
316
        printf("-x SOCKADDR\tBind AgentX to this address\n");
317
        printf("-c CONFFILE\tRead CONFFILE as a configuration file.\n");
318
        printf("-C\t\tDon't read the default configuration files.\n");
319
        printf("-L\t\tPrint warnings/messages to stdout/err\n");
320
        printf("-s\t\tLog warnings/messages to syslog\n");
321
        printf("-A\t\tAppend to the logfile rather than truncating it.\n");
322
        printf("-r Don't exit if root only accessible files can't be opened\n");
323
        printf("-l LOGFILE\tPrint warnings/messages to LOGFILE\n");
324
        printf("\t\t(By default LOGFILE=%s)\n",
325
#ifdef LOGFILE
326
                        LOGFILE
327
#else
328
                        "none"
329
#endif
330
              );
331
#if HAVE_UNISTD_H
332
        printf("-g \t\tChange to this gid after opening port\n");
333
        printf("-u \t\tChange to this uid after opening port\n");
334
#endif
335
        printf("\n");
336
        exit(1);
337
}
338
#endif // !defined(__ECOS)
339
 
340
        RETSIGTYPE
341
SnmpdShutDown(int a)
342
{
343
        running = 0;
344
}
345
 
346
#ifdef SIGHUP
347
        RETSIGTYPE
348
SnmpdReconfig(int a)
349
{
350
        reconfig = 1;
351
        signal(SIGHUP, SnmpdReconfig);
352
}
353
#endif
354
 
355
#ifdef SIGUSR1
356
extern void dump_registry( void );
357
        RETSIGTYPE
358
SnmpdDump(int a)
359
{
360
        dump_registry();
361
        signal(SIGUSR1, SnmpdDump);
362
}
363
#endif
364
 
365
 
366
        static void
367
SnmpTrapNodeDown(void)
368
{
369
    send_easy_trap (SNMP_TRAP_ENTERPRISESPECIFIC, 2);
370
    /* XXX  2 - Node Down #define it as NODE_DOWN_TRAP */
371
}
372
 
373
/*******************************************************************-o-******
374
 * main
375
 *
376
 * Parameters:
377
 *       argc
378
 *      *argv[]
379
 *
380
 * Returns:
381
 *      0        Always succeeds.  (?)
382
 *
383
 *
384
 * Setup and start the agent daemon.
385
 *
386
 * Also successfully EXITs with zero for some options.
387
 */
388
#if !defined(__ECOS)
389
 
390
        int
391
main(int argc, char *argv[])
392
{
393
        int             arg, i;
394
        int             ret;
395
        u_short         dest_port = SNMP_PORT;
396
        int             dont_fork = 0;
397
        char            logfile[SNMP_MAXBUF_SMALL];
398
        char           *cptr, **argvptr;
399
        char           *pid_file = NULL;
400
#if HAVE_GETPID
401
        FILE           *PID;
402
#endif
403
        int             dont_zero_log = 0;
404
        int             stderr_log=0, syslog_log=0;
405
        int             uid=0, gid=0;
406
 
407
        logfile[0]               = 0;
408
 
409
#ifdef LOGFILE
410
        strcpy(logfile, LOGFILE);
411
#endif
412
 
413
 
414
        /*
415
         * usage: snmpd
416
         */
417
        for (arg = 1; arg < argc; arg++)
418
          {
419
            if (argv[arg][0] == '-') {
420
              switch (argv[arg][1]) {
421
 
422
                case 'c':
423
                  if (++arg == argc)
424
                    usage(argv[0]);
425
                  ds_set_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG,
426
                                 argv[arg]);
427
                  break;
428
 
429
                case 'C':
430
                    ds_set_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS, 1);
431
                    break;
432
 
433
                case 'd':
434
                    snmp_set_dump_packet(++snmp_dump_packet);
435
                    ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE, 1);
436
                    break;
437
 
438
                case 'q':
439
                    snmp_set_quick_print(1);
440
                    break;
441
 
442
                case 'T':
443
                    if (argv[arg][2] != '\0')
444
                        cptr = &argv[arg][2];
445
                    else if (++arg>argc) {
446
                        fprintf(stderr,"Need UDP or TCP after -T flag.\n");
447
                        usage(argv[0]);
448
                        exit(1);
449
                    } else {
450
                        cptr = argv[arg];
451
                    }
452
                    if (strcasecmp(cptr,"TCP") == 0) {
453
                        ds_set_int(DS_APPLICATION_ID, DS_AGENT_FLAGS,
454
                                   ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS)
455
                                   | SNMP_FLAGS_STREAM_SOCKET);
456
                    } else if (strcasecmp(cptr,"UDP") == 0) {
457
                        /* default, do nothing */
458
                    } else {
459
                        fprintf(stderr,
460
                                "Unknown transport \"%s\" after -T flag.\n",
461
                                cptr);
462
                        usage(argv[0]);
463
                        exit(1);
464
                    }
465
                    break;
466
 
467
                case 'D':
468
                    debug_register_tokens(&argv[arg][2]);
469
                    snmp_set_do_debugging(1);
470
                    break;
471
 
472
                case 'p':
473
                  if (++arg == argc)
474
                    usage(argv[0]);
475
                  dest_port = atoi(argv[arg]);
476
                  if (dest_port <= 0)
477
                    usage(argv[0]);
478
                  break;
479
 
480
                case 'x':
481
                  if (++arg == argc)
482
                    usage(argv[0]);
483
                  ds_set_string(DS_APPLICATION_ID, DS_AGENT_X_SOCKET, argv[arg]);
484
                  break;
485
 
486
                case 'r':
487
                    ds_set_boolean(DS_APPLICATION_ID,
488
                                      DS_AGENT_NO_ROOT_ACCESS, 1);
489
                    break;
490
 
491
                case 'P':
492
                  if (++arg == argc)
493
                    usage(argv[0]);
494
                  pid_file = argv[arg];
495
 
496
                case 'a':
497
                      log_addresses++;
498
                  break;
499
 
500
                case 'V':
501
                  ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE, 1);
502
                  break;
503
 
504
                case 'f':
505
                  dont_fork = 1;
506
                  break;
507
 
508
                case 'l':
509
                  if (++arg == argc)
510
                    usage(argv[0]);
511
                  strcpy(logfile, argv[arg]);
512
                  break;
513
 
514
                case 'L':
515
                    stderr_log=1;
516
                    break;
517
 
518
                case 's':
519
                    syslog_log=1;
520
                    break;
521
 
522
                case 'A':
523
                    dont_zero_log = 1;
524
                    break;
525
#if HAVE_UNISTD_H
526
                case 'u':
527
                  if (++arg == argc) usage(argv[0]);
528
                  uid = atoi(argv[arg]);
529
                  break;
530
                case 'g':
531
                  if (++arg == argc) usage(argv[0]);
532
                  gid = atoi(argv[arg]);
533
                  break;
534
#endif
535
                case 'h':
536
                  usage(argv[0]);
537
                  break;
538
                case 'H':
539
                  init_agent("snmpd");   /* register our .conf handlers */
540
                  init_mib_modules();
541
                  init_snmp("snmpd");
542
                  fprintf(stderr, "Configuration directives understood:\n");
543
                  read_config_print_usage("  ");
544
                  exit(0);
545
                case 'v':
546
                  printf("\nUCD-snmp version:  %s\n",VersionInfo);
547
                  printf("Author:            Wes Hardaker\n");
548
                  printf("Email:             ucd-snmp-coders@ucd-snmp.ucdavis.edu\n\n");
549
                  exit (0);
550
                case '-':
551
                  switch(argv[arg][2]){
552
                    case 'v':
553
                      printf("\nUCD-snmp version:  %s\n",VersionInfo);
554
                      printf("Author:            Wes Hardaker\n");
555
                      printf("Email:             ucd-snmp-coders@ucd-snmp.ucdavis.edu\n\n");
556
                      exit (0);
557
                    case 'h':
558
                      usage(argv[0]);
559
                      exit(0);
560
                  }
561
 
562
                default:
563
                  printf("invalid option: %s\n", argv[arg]);
564
                  usage(argv[0]);
565
                  break;
566
              }
567
              continue;
568
            }
569
        }  /* end-for */
570
 
571
        /*
572
         * Initialize a argv set to the current for restarting the agent.
573
         */
574
        argvrestartp = (char **) malloc((argc + 2) * sizeof(char *));
575
        argvptr = argvrestartp;
576
        for (i = 0, ret = 1; i < argc; i++) {
577
                ret += strlen(argv[i]) + 1;
578
        }
579
        argvrestart = (char *) malloc(ret);
580
        argvrestartname = (char *) malloc(strlen(argv[0]) + 1);
581
        strcpy(argvrestartname, argv[0]);
582
        if ( strstr(argvrestartname, "agentxd") != NULL)
583
          ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, SUB_AGENT);
584
        else
585
          ds_set_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE, MASTER_AGENT);
586
        for (cptr = argvrestart, i = 0; i < argc; i++) {
587
                strcpy(cptr, argv[i]);
588
                *(argvptr++) = cptr;
589
                cptr += strlen(argv[i]) + 1;
590
        }
591
        *cptr = 0;
592
        *argvptr = NULL;
593
 
594
 
595
        /*
596
         * Open the logfile if necessary.
597
         */
598
 
599
        /* Should open logfile and/or syslog based on arguments */
600
        if (logfile[0])
601
                snmp_enable_filelog(logfile, dont_zero_log);
602
        if (syslog_log)
603
                snmp_enable_syslog();
604
#ifdef BUFSIZ
605
        setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
606
#endif
607
    /*
608
     * Initialize the world.  Detach from the shell.
609
     * Create initial user.
610
     */
611
#if HAVE_FORK
612
    if (!dont_fork && fork() != 0) {
613
      exit(0);
614
    }
615
#endif
616
 
617
#if HAVE_GETPID
618
    if (pid_file != NULL) {
619
      if ((PID = fopen(pid_file, "w")) == NULL) {
620
        snmp_log_perror("fopen");
621
        if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS))
622
          exit(1);
623
      }
624
      else {
625
        fprintf(PID, "%d\n", (int)getpid());
626
        fclose(PID);
627
      }
628
    }
629
#endif
630
 
631
#else /* __ECOS environment: */
632
void snmpd( void *initfunc( void ) ) {
633
    int             ret;
634
    u_short         dest_port = SNMP_PORT;
635
#define stderr_log 1
636
#endif
637
 
638
    // ---------
639
    // En-bloc reinitialization of statics.
640
    running = 1;
641
    // ---------
642
 
643
    SOCK_STARTUP;
644
    init_agent("snmpd");                /* do what we need to do first. */
645
    init_mib_modules();
646
 
647
 
648
    /* start library */
649
    init_snmp("snmpd");
650
 
651
    ret = init_master_agent( dest_port,
652
                       snmp_check_packet,
653
                       snmp_check_parse );
654
        if( ret != 0 )
655
                Exit(1); /* Exit logs exit val for us */
656
 
657
#ifdef SIGTERM
658
    signal(SIGTERM, SnmpdShutDown);
659
#endif
660
#ifdef SIGINT
661
    signal(SIGINT, SnmpdShutDown);
662
#endif
663
#ifdef SIGHUP
664
    signal(SIGHUP, SnmpdReconfig);
665
#endif
666
#ifdef SIGUSR1
667
    signal(SIGUSR1, SnmpdDump);
668
#endif
669
 
670
    /* send coldstart trap via snmptrap(1) if possible */
671
    send_easy_trap (0, 0);
672
 
673
#if HAVE_UNISTD_H
674
        if (gid) {
675
                DEBUGMSGTL(("snmpd", "Changing gid to %d.\n", gid));
676
                if (setgid(gid)==-1) {
677
                        snmp_log_perror("setgid failed");
678
                        if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS))
679
                          exit(1);
680
                }
681
        }
682
        if (uid) {
683
                DEBUGMSGTL(("snmpd", "Changing uid to %d.\n", uid));
684
                if(setuid(uid)==-1) {
685
                        snmp_log_perror("setuid failed");
686
                        if (!ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_NO_ROOT_ACCESS))
687
                          exit(1);
688
                }
689
        }
690
#endif
691
 
692
        /* honor selection of standard error output */
693
        if (!stderr_log)
694
                snmp_disable_stderrlog();
695
 
696
        /* we're up, log our version number */
697
        snmp_log(LOG_INFO, "UCD-SNMP version %s\n", VersionInfo);
698
 
699
        memset(addrCache, 0, sizeof(addrCache));
700
 
701
        /*
702
         * Call initialization function if necessary
703
         */
704
        DEBUGMSGTL(("snmpd", "Calling initfunc().\n"));
705
        if ( initfunc )
706
            (initfunc)();
707
 
708
        /*
709
         * Forever monitor the dest_port for incoming PDUs.
710
         */
711
        DEBUGMSGTL(("snmpd", "We're up.  Starting to process data.\n"));
712
        receive();
713
#include "mib_module_shutdown.h"
714
        DEBUGMSGTL(("snmpd", "sending shutdown trap\n"));
715
        SnmpTrapNodeDown();
716
        DEBUGMSGTL(("snmpd", "Bye...\n"));
717
        snmp_shutdown("snmpd");
718
 
719
}  /* End main() -- snmpd */
720
 
721
/*******************************************************************-o-******
722
 * receive
723
 *
724
 * Parameters:
725
 *
726
 * Returns:
727
 *      0        On success.
728
 *      -1      System error.
729
 *
730
 * Infinite while-loop which monitors incoming messges for the agent.
731
 * Invoke the established message handlers for incoming messages on a per
732
 * port basis.  Handle timeouts.
733
 */
734
        static int
735
receive(void)
736
{
737
    int numfds;
738
    fd_set fdset;
739
    struct timeval      timeout, *tvp = &timeout;
740
    struct timeval      sched,   *svp = &sched,
741
                        now,     *nvp = &now;
742
    int count, block;
743
#ifdef  USING_SMUX_MODULE
744
    int i, sd;
745
#endif  /* USING_SMUX_MODULE */
746
 
747
 
748
    /*
749
     * Set the 'sched'uled timeout to the current time + one TIMETICK.
750
     */
751
    gettimeofday(nvp, (struct timezone *) NULL);
752
    svp->tv_usec = nvp->tv_usec + TIMETICK;
753
    svp->tv_sec = nvp->tv_sec;
754
 
755
    while (svp->tv_usec >= ONE_SEC){
756
        svp->tv_usec -= ONE_SEC;
757
        svp->tv_sec++;
758
    }
759
 
760
    /*
761
     * Loop-forever: execute message handlers for sockets with data,
762
     * reset the 'sched'uler.
763
     */
764
    while (running) {
765
        if (reconfig) {
766
          reconfig = 0;
767
          snmp_log(LOG_INFO, "Reconfiguring daemon\n");
768
          update_config();
769
        }
770
        tvp =  &timeout;
771
        tvp->tv_sec = 0;
772
        tvp->tv_usec = TIMETICK;
773
 
774
        numfds = 0;
775
        FD_ZERO(&fdset);
776
        block = 0;
777
        snmp_select_info(&numfds, &fdset, tvp, &block);
778
        if (block == 1)
779
            tvp = NULL; /* block without timeout */
780
 
781
#ifdef  USING_SMUX_MODULE
782
                if (smux_listen_sd >= 0) {
783
                        FD_SET(smux_listen_sd, &fdset);
784
                        numfds = smux_listen_sd >= numfds ? smux_listen_sd + 1 : numfds;
785
                        for (i = 0; i < sdlen; i++) {
786
                                FD_SET(sdlist[i], &fdset);
787
                                numfds = sdlist[i] >= numfds ? sdlist[i] + 1 : numfds;
788
                        }
789
                }
790
#endif  /* USING_SMUX_MODULE */
791
 
792
        count = select(numfds, &fdset, 0, 0, tvp);
793
 
794
        if (count > 0){
795
            snmp_read(&fdset);
796
        } else switch(count){
797
            case 0:
798
                snmp_timeout();
799
                break;
800
            case -1:
801
                if (errno == EINTR){
802
                    continue;
803
                } else {
804
                    snmp_log_perror("select");
805
                }
806
                return -1;
807
            default:
808
                snmp_log(LOG_ERR, "select returned %d\n", count);
809
                return -1;
810
        }  /* endif -- count>0 */
811
 
812
#ifdef  USING_SMUX_MODULE
813
                /* handle the SMUX sd's */
814
                if (smux_listen_sd >= 0) {
815
                        for (i = 0; i < sdlen; i++) {
816
                                if (FD_ISSET(sdlist[i], &fdset)) {
817
                                        if (smux_process(sdlist[i]) < 0) {
818
                                                for (; i < (sdlen - 1); i++) {
819
                                                        sdlist[i] = sdlist[i+1];
820
                                                }
821
                                                sdlen--;
822
                                        }
823
                                }
824
                        }
825
                        /* new connection */
826
                        if (FD_ISSET(smux_listen_sd, &fdset)) {
827
                                if ((sd = smux_accept(smux_listen_sd)) >= 0) {
828
                                        sdlist[sdlen++] = sd;
829
                                }
830
                        }
831
                }
832
#endif  /* USING_SMUX_MODULE */
833
 
834
 
835
 
836
        /*
837
         * If the time 'now' is greater than the 'sched'uled time, then:
838
         *
839
         *    Check alarm and event timers.
840
         *    Reset the 'sched'uled time to current time + one TIMETICK.
841
         *    Age the cache network addresses (from whom messges have
842
         *        been received).
843
         */
844
        gettimeofday(nvp, (struct timezone *) NULL);
845
 
846
        if (nvp->tv_sec > svp->tv_sec
847
                || (nvp->tv_sec == svp->tv_sec && nvp->tv_usec > svp->tv_usec)){
848
            svp->tv_usec = nvp->tv_usec + TIMETICK;
849
            svp->tv_sec = nvp->tv_sec;
850
 
851
            while (svp->tv_usec >= ONE_SEC){
852
                svp->tv_usec -= ONE_SEC;
853
                svp->tv_sec++;
854
            }
855
            if (log_addresses && lastAddrAge++ > 600){
856
 
857
                lastAddrAge = 0;
858
                for(count = 0; count < ADDRCACHE; count++){
859
                    if (addrCache[count].status == OLD)
860
                        addrCache[count].status = UNUSED;
861
                    if (addrCache[count].status == USED)
862
                        addrCache[count].status = OLD;
863
                }
864
            }
865
        }  /* endif -- now>sched */
866
 
867
        /* run requested alarms */
868
        run_alarms();
869
 
870
    }  /* endwhile */
871
 
872
    snmp_log(LOG_INFO, "Received TERM or STOP signal...  shutting down...\n");
873
    return 0;
874
 
875
}  /* end receive() */
876
 
877
 
878
 
879
 
880
/*******************************************************************-o-******
881
 * snmp_check_packet
882
 *
883
 * Parameters:
884
 *      session, from
885
 *
886
 * Returns:
887
 *      1       On success.
888
 *      0        On error.
889
 *
890
 * Handler for all incoming messages (a.k.a. packets) for the agent.  If using
891
 * the libwrap utility, log the connection and deny/allow the access. Print
892
 * output when appropriate, and increment the incoming counter.
893
 *
894
 */
895
int
896
snmp_check_packet(struct snmp_session *session,
897
  snmp_ipaddr from)
898
{
899
    struct sockaddr_in *fromIp = (struct sockaddr_in *)&from;
900
 
901
#ifdef USE_LIBWRAP
902
    const char *addr_string;
903
    /*
904
     * Log the message and/or dump the message.
905
     * Optionally cache the network address of the sender.
906
     */
907
    addr_string = inet_ntoa(fromIp->sin_addr);
908
 
909
    if(!addr_string) {
910
      addr_string = STRING_UNKNOWN;
911
    }
912
    if(hosts_ctl("snmpd", addr_string, addr_string, STRING_UNKNOWN)) {
913
      snmp_log(allow_severity, "Connection from %s\n", addr_string);
914
    } else {
915
      snmp_log(deny_severity, "Connection from %s REFUSED\n", addr_string);
916
      return(0);
917
    }
918
#endif  /* USE_LIBWRAP */
919
 
920
    snmp_increment_statistic(STAT_SNMPINPKTS);
921
 
922
    if (log_addresses || ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)){
923
        int count;
924
 
925
        for(count = 0; count < ADDRCACHE; count++){
926
            if (addrCache[count].status > UNUSED /* used or old */
927
                && fromIp->sin_addr.s_addr == addrCache[count].addr)
928
                break;
929
        }
930
 
931
        if (count >= ADDRCACHE ||
932
            ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)){
933
            snmp_log(LOG_INFO, "Received SNMP packet(s) from %s\n",
934
                        inet_ntoa(fromIp->sin_addr));
935
            for(count = 0; count < ADDRCACHE; count++){
936
                if (addrCache[count].status == UNUSED){
937
                    addrCache[count].addr = fromIp->sin_addr.s_addr;
938
                    addrCache[count].status = USED;
939
                    break;
940
                }
941
            }
942
        } else {
943
            addrCache[count].status = USED;
944
        }
945
    }
946
 
947
    return ( 1 );
948
}
949
 
950
 
951
int
952
snmp_check_parse( struct snmp_session *session,
953
    struct snmp_pdu     *pdu,
954
    int    result)
955
{
956
    if ( result == 0 ) {
957
        if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE) &&
958
             snmp_get_do_logging() ) {
959
             char c_oid [SPRINT_MAX_LEN];
960
             struct variable_list *var_ptr;
961
 
962
            switch (pdu->command) {
963
            case SNMP_MSG_GET:
964
                snmp_log(LOG_DEBUG, "  GET message\n"); break;
965
            case SNMP_MSG_GETNEXT:
966
                snmp_log(LOG_DEBUG, "  GETNEXT message\n"); break;
967
            case SNMP_MSG_RESPONSE:
968
                snmp_log(LOG_DEBUG, "  RESPONSE message\n"); break;
969
            case SNMP_MSG_SET:
970
                snmp_log(LOG_DEBUG, "  SET message\n"); break;
971
            case SNMP_MSG_TRAP:
972
                snmp_log(LOG_DEBUG, "  TRAP message\n"); break;
973
            case SNMP_MSG_GETBULK:
974
                snmp_log(LOG_DEBUG, "  GETBULK message, non-rep=%d, max_rep=%d\n",
975
                        pdu->errstat, pdu->errindex); break;
976
            case SNMP_MSG_INFORM:
977
                snmp_log(LOG_DEBUG, "  INFORM message\n"); break;
978
            case SNMP_MSG_TRAP2:
979
                snmp_log(LOG_DEBUG, "  TRAP2 message\n"); break;
980
            case SNMP_MSG_REPORT:
981
                snmp_log(LOG_DEBUG, "  REPORT message\n"); break;
982
            }
983
 
984
            for ( var_ptr = pdu->variables ;
985
                var_ptr != NULL ; var_ptr=var_ptr->next_variable )
986
            {
987
                sprint_objid (c_oid, var_ptr->name, var_ptr->name_length);
988
                snmp_log(LOG_DEBUG, "    -- %s\n", c_oid);
989
            }
990
        }
991
        return 1;
992
    }
993
    return 0; /* XXX: does it matter what the return value is? */
994
}
995
 
996
/*******************************************************************-o-******
997
 * snmp_input
998
 *
999
 * Parameters:
1000
 *       op
1001
 *      *session
1002
 *       requid
1003
 *      *pdu
1004
 *      *magic
1005
 *
1006
 * Returns:
1007
 *      1               On success      -OR-
1008
 *      Passes through  Return from alarmGetResponse() when
1009
 *                        USING_V2PARTY_ALARM_MODULE is defined.
1010
 *
1011
 * Call-back function to manage responses to traps (informs) and alarms.
1012
 * Not used by the agent to process other Response PDUs.
1013
 */
1014
int
1015
snmp_input(int op,
1016
           struct snmp_session *session,
1017
           int reqid,
1018
           struct snmp_pdu *pdu,
1019
           void *magic)
1020
{
1021
    struct get_req_state *state = (struct get_req_state *)magic;
1022
 
1023
    if (op == RECEIVED_MESSAGE) {
1024
        if (pdu->command == SNMP_MSG_GET) {
1025
            if (state->type == EVENT_GET_REQ) {
1026
                /* this is just the ack to our inform pdu */
1027
                return 1;
1028
            }
1029
        }
1030
    }
1031
    else if (op == TIMED_OUT) {
1032
        if (state->type == ALARM_GET_REQ) {
1033
                /* Need a mechanism to replace obsolete SNMPv2p alarm */
1034
        }
1035
    }
1036
    return 1;
1037
 
1038
}  /* end snmp_input() */

powered by: WebSVN 2.1.0

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