added files
[bcm963xx.git] / userapps / opensource / net-snmp / apps / snmptrap.c
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 }