~ubuntu-branches/ubuntu/gutsy/net-snmp/gutsy-security

« back to all changes in this revision

Viewing changes to apps/snmptrap.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * snmptrap.c - send snmp traps to a network entity.
 
3
 *
 
4
 */
 
5
/******************************************************************
 
6
        Copyright 1989, 1991, 1992 by Carnegie Mellon University
 
7
 
 
8
                      All Rights Reserved
 
9
 
 
10
Permission to use, copy, modify, and distribute this software and its
 
11
documentation for any purpose and without fee is hereby granted,
 
12
provided that the above copyright notice appear in all copies and that
 
13
both that copyright notice and this permission notice appear in
 
14
supporting documentation, and that the name of CMU not be
 
15
used in advertising or publicity pertaining to distribution of the
 
16
software without specific, written prior permission.
 
17
 
 
18
CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
19
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
20
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
21
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
22
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
23
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
24
SOFTWARE.
 
25
******************************************************************/
 
26
#include <net-snmp/net-snmp-config.h>
 
27
 
 
28
#if HAVE_STDLIB_H
 
29
#include <stdlib.h>
 
30
#endif
 
31
#if HAVE_UNISTD_H
 
32
#include <unistd.h>
 
33
#endif
 
34
#if HAVE_STRING_H
 
35
#include <string.h>
 
36
#else
 
37
#include <strings.h>
 
38
#endif
 
39
#include <sys/types.h>
 
40
#if HAVE_NETINET_IN_H
 
41
# include <netinet/in.h>
 
42
#endif
 
43
#if TIME_WITH_SYS_TIME
 
44
# ifdef WIN32
 
45
#  include <sys/timeb.h>
 
46
# else
 
47
#  include <sys/time.h>
 
48
# endif
 
49
# include <time.h>
 
50
#else
 
51
# if HAVE_SYS_TIME_H
 
52
#  include <sys/time.h>
 
53
# else
 
54
#  include <time.h>
 
55
# endif
 
56
#endif
 
57
#if HAVE_SYS_SELECT_H
 
58
#include <sys/select.h>
 
59
#endif
 
60
#include <stdio.h>
 
61
#if HAVE_WINSOCK_H
 
62
#include <winsock.h>
 
63
#endif
 
64
#if HAVE_SYS_SOCKET_H
 
65
#include <sys/socket.h>
 
66
#endif
 
67
#if HAVE_NETDB_H
 
68
#include <netdb.h>
 
69
#endif
 
70
#if HAVE_ARPA_INET_H
 
71
#include <arpa/inet.h>
 
72
#endif
 
73
 
 
74
#include <net-snmp/net-snmp-includes.h>
 
75
 
 
76
oid             objid_enterprise[] = { 1, 3, 6, 1, 4, 1, 3, 1, 1 };
 
77
oid             objid_sysdescr[] = { 1, 3, 6, 1, 2, 1, 1, 1, 0 };
 
78
oid             objid_sysuptime[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
 
79
oid             objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
 
80
int             inform = 0;
 
81
 
 
82
void
 
83
usage(void)
 
84
{
 
85
    fprintf(stderr, "USAGE: %s ", inform ? "snmpinform" : "snmptrap");
 
86
    snmp_parse_args_usage(stderr);
 
87
    fprintf(stderr, " TRAP-PARAMETERS\n\n");
 
88
    snmp_parse_args_descriptions(stderr);
 
89
    fprintf(stderr,
 
90
            "  -C APPOPTS\t\tSet various application specific behaviour:\n");
 
91
    fprintf(stderr, "\t\t\t  i:  send an INFORM instead of a TRAP\n");
 
92
    fprintf(stderr,
 
93
            "\n  -v 1 TRAP-PARAMETERS:\n\t enterprise-oid agent trap-type specific-type uptime [OID TYPE VALUE]...\n");
 
94
    fprintf(stderr, "  or\n");
 
95
    fprintf(stderr,
 
96
            "  -v 2 TRAP-PARAMETERS:\n\t uptime trapoid [OID TYPE VALUE] ...\n");
 
97
}
 
98
 
 
99
int
 
100
snmp_input(int operation,
 
101
           netsnmp_session * session,
 
102
           int reqid, netsnmp_pdu *pdu, void *magic)
 
103
{
 
104
    return 1;
 
105
}
 
106
 
 
107
in_addr_t
 
108
parse_address(char *address)
 
109
{
 
110
    in_addr_t       addr;
 
111
    struct sockaddr_in saddr;
 
112
    struct hostent *hp;
 
113
 
 
114
    if ((addr = inet_addr(address)) != -1)
 
115
        return addr;
 
116
    hp = gethostbyname(address);
 
117
    if (hp == NULL) {
 
118
        fprintf(stderr, "unknown host: %s\n", address);
 
119
        exit(1);
 
120
    } else {
 
121
        memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length);
 
122
        return saddr.sin_addr.s_addr;
 
123
    }
 
124
 
 
125
}
 
126
 
 
127
static void
 
128
optProc(int argc, char *const *argv, int opt)
 
129
{
 
130
    switch (opt) {
 
131
    case 'C':
 
132
        while (*optarg) {
 
133
            switch (*optarg++) {
 
134
            case 'i':
 
135
                inform = 1;
 
136
                break;
 
137
            default:
 
138
                fprintf(stderr,
 
139
                        "Unknown flag passed to -C: %c\n", optarg[-1]);
 
140
                exit(1);
 
141
            }
 
142
        }
 
143
        break;
 
144
    }
 
145
}
 
146
 
 
147
int
 
148
main(int argc, char *argv[])
 
149
{
 
150
    netsnmp_session session, *ss;
 
151
    netsnmp_pdu    *pdu, *response;
 
152
    in_addr_t      *pdu_in_addr_t;
 
153
    oid             name[MAX_OID_LEN];
 
154
    size_t          name_length;
 
155
    int             arg;
 
156
    int             status;
 
157
    char           *trap = NULL, *specific = NULL, *description =
 
158
        NULL, *agent = NULL;
 
159
    char           *prognam;
 
160
    int             exitval = 0;
 
161
 
 
162
    prognam = strrchr(argv[0], '/');
 
163
    if (prognam)
 
164
        prognam++;
 
165
    else
 
166
        prognam = argv[0];
 
167
 
 
168
    putenv(strdup("POSIXLY_CORRECT=1"));
 
169
 
 
170
    if (strcmp(prognam, "snmpinform") == 0)
 
171
        inform = 1;
 
172
    switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) {
 
173
    case -2:
 
174
        exit(0);
 
175
    case -1:
 
176
        usage();
 
177
        exit(1);
 
178
    default:
 
179
        break;
 
180
    }
 
181
 
 
182
    SOCK_STARTUP;
 
183
 
 
184
    session.callback = snmp_input;
 
185
    session.callback_magic = NULL;
 
186
    netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_DEFAULT_PORT, 
 
187
                       SNMP_TRAP_PORT);
 
188
 
 
189
    if (session.version == SNMP_VERSION_3 && !inform) {
 
190
        /*
 
191
         * for traps, we use ourselves as the authoritative engine
 
192
         * which is really stupid since command line apps don't have a
 
193
         * notion of a persistent engine.  Hence, our boots and time
 
194
         * values are probably always really wacked with respect to what
 
195
         * a manager would like to see.
 
196
         * 
 
197
         * The following should be enough to:
 
198
         * 
 
199
         * 1) prevent the library from doing discovery for engineid & time.
 
200
         * 2) use our engineid instead of the remote engineid for
 
201
         * authoritative & privacy related operations.
 
202
         * 3) The remote engine must be configured with users for our engineID.
 
203
         * 
 
204
         * -- Wes 
 
205
         */
 
206
 
 
207
        /*
 
208
         * setup the engineID based on IP addr.  Need a different
 
209
         * algorthim here.  This will cause problems with agents on the
 
210
         * same machine sending traps. 
 
211
         */
 
212
        setup_engineID(NULL, NULL);
 
213
 
 
214
        /*
 
215
         * pick our own engineID 
 
216
         */
 
217
        if (session.securityEngineIDLen == 0 ||
 
218
            session.securityEngineID == NULL) {
 
219
            session.securityEngineID =
 
220
                snmpv3_generate_engineID(&session.securityEngineIDLen);
 
221
        }
 
222
        if (session.contextEngineIDLen == 0 ||
 
223
            session.contextEngineID == NULL) {
 
224
            session.contextEngineID =
 
225
                snmpv3_generate_engineID(&session.contextEngineIDLen);
 
226
        }
 
227
 
 
228
        /*
 
229
         * set boots and time, which will cause problems if this
 
230
         * machine ever reboots and a remote trap receiver has cached our
 
231
         * boots and time...  I'll cause a not-in-time-window report to
 
232
         * be sent back to this machine. 
 
233
         */
 
234
        if (session.engineBoots == 0)
 
235
            session.engineBoots = 1;
 
236
        if (session.engineTime == 0)    /* not really correct, */
 
237
            session.engineTime = get_uptime();  /* but it'll work. Sort of. */
 
238
    }
 
239
 
 
240
    ss = snmp_open(&session);
 
241
    if (ss == NULL) {
 
242
        /*
 
243
         * diagnose snmp_open errors with the input netsnmp_session pointer 
 
244
         */
 
245
        snmp_sess_perror("snmptrap", &session);
 
246
        SOCK_CLEANUP;
 
247
        exit(1);
 
248
    }
 
249
 
 
250
    if (session.version == SNMP_VERSION_1) {
 
251
        if (inform) {
 
252
            fprintf(stderr, "Cannot send INFORM as SNMPv1 PDU\n");
 
253
            exit(1);
 
254
        }
 
255
        pdu = snmp_pdu_create(SNMP_MSG_TRAP);
 
256
        pdu_in_addr_t = (in_addr_t *) pdu->agent_addr;
 
257
        if (arg == argc) {
 
258
            fprintf(stderr, "No enterprise oid\n");
 
259
            usage();
 
260
            SOCK_CLEANUP;
 
261
            exit(1);
 
262
        }
 
263
        if (argv[arg][0] == 0) {
 
264
            pdu->enterprise = (oid *) malloc(sizeof(objid_enterprise));
 
265
            memcpy(pdu->enterprise, objid_enterprise,
 
266
                   sizeof(objid_enterprise));
 
267
            pdu->enterprise_length =
 
268
                sizeof(objid_enterprise) / sizeof(oid);
 
269
        } else {
 
270
            name_length = MAX_OID_LEN;
 
271
            if (!snmp_parse_oid(argv[arg], name, &name_length)) {
 
272
                snmp_perror(argv[arg]);
 
273
                usage();
 
274
                SOCK_CLEANUP;
 
275
                exit(1);
 
276
            }
 
277
            pdu->enterprise = (oid *) malloc(name_length * sizeof(oid));
 
278
            memcpy(pdu->enterprise, name, name_length * sizeof(oid));
 
279
            pdu->enterprise_length = name_length;
 
280
        }
 
281
        if (++arg >= argc) {
 
282
            fprintf(stderr, "Missing agent parameter\n");
 
283
            usage();
 
284
            SOCK_CLEANUP;
 
285
            exit(1);
 
286
        }
 
287
        agent = argv[arg];
 
288
        if (agent != NULL && strlen(agent) != 0) {
 
289
            *pdu_in_addr_t = parse_address(agent);
 
290
        } else {
 
291
            *pdu_in_addr_t = get_myaddr();
 
292
        }
 
293
        if (++arg == argc) {
 
294
            fprintf(stderr, "Missing generic-trap parameter\n");
 
295
            usage();
 
296
            SOCK_CLEANUP;
 
297
            exit(1);
 
298
        }
 
299
        trap = argv[arg];
 
300
        pdu->trap_type = atoi(trap);
 
301
        if (++arg == argc) {
 
302
            fprintf(stderr, "Missing specific-trap parameter\n");
 
303
            usage();
 
304
            SOCK_CLEANUP;
 
305
            exit(1);
 
306
        }
 
307
        specific = argv[arg];
 
308
        pdu->specific_type = atoi(specific);
 
309
        if (++arg == argc) {
 
310
            fprintf(stderr, "Missing uptime parameter\n");
 
311
            usage();
 
312
            SOCK_CLEANUP;
 
313
            exit(1);
 
314
        }
 
315
        description = argv[arg];
 
316
        if (description == NULL || *description == 0)
 
317
            pdu->time = get_uptime();
 
318
        else
 
319
            pdu->time = atol(description);
 
320
    } else {
 
321
        long            sysuptime;
 
322
        char            csysuptime[20];
 
323
 
 
324
        pdu = snmp_pdu_create(inform ? SNMP_MSG_INFORM : SNMP_MSG_TRAP2);
 
325
        if (arg == argc) {
 
326
            fprintf(stderr, "Missing up-time parameter\n");
 
327
            usage();
 
328
            SOCK_CLEANUP;
 
329
            exit(1);
 
330
        }
 
331
        trap = argv[arg];
 
332
        if (*trap == 0) {
 
333
            sysuptime = get_uptime();
 
334
            sprintf(csysuptime, "%ld", sysuptime);
 
335
            trap = csysuptime;
 
336
        }
 
337
        snmp_add_var(pdu, objid_sysuptime,
 
338
                     sizeof(objid_sysuptime) / sizeof(oid), 't', trap);
 
339
        if (++arg == argc) {
 
340
            fprintf(stderr, "Missing trap-oid parameter\n");
 
341
            usage();
 
342
            SOCK_CLEANUP;
 
343
            exit(1);
 
344
        }
 
345
        if (snmp_add_var
 
346
            (pdu, objid_snmptrap, sizeof(objid_snmptrap) / sizeof(oid),
 
347
             'o', argv[arg]) != 0) {
 
348
            snmp_perror(argv[arg]);
 
349
            SOCK_CLEANUP;
 
350
            exit(1);
 
351
        }
 
352
    }
 
353
    arg++;
 
354
 
 
355
    while (arg < argc) {
 
356
        arg += 3;
 
357
        if (arg > argc) {
 
358
            fprintf(stderr, "%s: Missing type/value for variable\n",
 
359
                    argv[arg - 3]);
 
360
            SOCK_CLEANUP;
 
361
            exit(1);
 
362
        }
 
363
        name_length = MAX_OID_LEN;
 
364
        if (!snmp_parse_oid(argv[arg - 3], name, &name_length)) {
 
365
            snmp_perror(argv[arg - 3]);
 
366
            SOCK_CLEANUP;
 
367
            exit(1);
 
368
        }
 
369
        if (snmp_add_var
 
370
            (pdu, name, name_length, argv[arg - 2][0],
 
371
             argv[arg - 1]) != 0) {
 
372
            snmp_perror(argv[arg - 3]);
 
373
            SOCK_CLEANUP;
 
374
            exit(1);
 
375
        }
 
376
    }
 
377
 
 
378
    if (inform)
 
379
        status = snmp_synch_response(ss, pdu, &response);
 
380
    else
 
381
        status = snmp_send(ss, pdu) == 0;
 
382
    if (status) {
 
383
        snmp_sess_perror(inform ? "snmpinform" : "snmptrap", ss);
 
384
        if (!inform)
 
385
            snmp_free_pdu(pdu);
 
386
        exitval = 1;
 
387
    } else if (inform)
 
388
        snmp_free_pdu(response);
 
389
 
 
390
    snmp_close(ss);
 
391
    SOCK_CLEANUP;
 
392
    return exitval;
 
393
}