summaryrefslogtreecommitdiff
path: root/apps/snmptrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/snmptrap.c')
-rw-r--r--apps/snmptrap.c392
1 files changed, 392 insertions, 0 deletions
diff --git a/apps/snmptrap.c b/apps/snmptrap.c
new file mode 100644
index 0000000..7c086db
--- /dev/null
+++ b/apps/snmptrap.c
@@ -0,0 +1,392 @@
+/*
+ * snmptrap.c - send snmp traps to a network entity.
+ *
+ */
+/******************************************************************
+ Copyright 1989, 1991, 1992 by Carnegie Mellon University
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of CMU not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+******************************************************************/
+#include <net-snmp/net-snmp-config.h>
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#include <sys/types.h>
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#if HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#include <stdio.h>
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include <net-snmp/net-snmp-includes.h>
+
+oid objid_enterprise[] = { 1, 3, 6, 1, 4, 1, 3, 1, 1 };
+oid objid_sysdescr[] = { 1, 3, 6, 1, 2, 1, 1, 1, 0 };
+oid objid_sysuptime[] = { 1, 3, 6, 1, 2, 1, 1, 3, 0 };
+oid objid_snmptrap[] = { 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0 };
+int inform = 0;
+
+void
+usage(void)
+{
+ fprintf(stderr, "USAGE: %s ", inform ? "snmpinform" : "snmptrap");
+ snmp_parse_args_usage(stderr);
+ fprintf(stderr, " TRAP-PARAMETERS\n\n");
+ snmp_parse_args_descriptions(stderr);
+ fprintf(stderr,
+ " -C APPOPTS\t\tSet various application specific behaviour:\n");
+ fprintf(stderr, "\t\t\t i: send an INFORM instead of a TRAP\n");
+ fprintf(stderr,
+ "\n -v 1 TRAP-PARAMETERS:\n\t enterprise-oid agent trap-type specific-type uptime [OID TYPE VALUE]...\n");
+ fprintf(stderr, " or\n");
+ fprintf(stderr,
+ " -v 2 TRAP-PARAMETERS:\n\t uptime trapoid [OID TYPE VALUE] ...\n");
+}
+
+int
+snmp_input(int operation,
+ netsnmp_session * session,
+ int reqid, netsnmp_pdu *pdu, void *magic)
+{
+ return 1;
+}
+
+static void
+optProc(int argc, char *const *argv, int opt)
+{
+ switch (opt) {
+ case 'C':
+ while (*optarg) {
+ switch (*optarg++) {
+ case 'i':
+ inform = 1;
+ break;
+ default:
+ fprintf(stderr,
+ "Unknown flag passed to -C: %c\n", optarg[-1]);
+ exit(1);
+ }
+ }
+ break;
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ netsnmp_session session, *ss;
+ netsnmp_pdu *pdu, *response;
+ oid name[MAX_OID_LEN];
+ size_t name_length;
+ int arg;
+ int status;
+ char *trap = NULL;
+ char *prognam;
+ int exitval = 0;
+#ifndef NETSNMP_DISABLE_SNMPV1
+ char *specific = NULL, *description = NULL, *agent = NULL;
+ in_addr_t *pdu_in_addr_t;
+#endif
+
+ prognam = strrchr(argv[0], '/');
+ if (prognam)
+ prognam++;
+ else
+ prognam = argv[0];
+
+ putenv(strdup("POSIXLY_CORRECT=1"));
+
+ if (strcmp(prognam, "snmpinform") == 0)
+ inform = 1;
+ switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) {
+ case NETSNMP_PARSE_ARGS_ERROR:
+ exit(1);
+ case NETSNMP_PARSE_ARGS_SUCCESS_EXIT:
+ exit(0);
+ case NETSNMP_PARSE_ARGS_ERROR_USAGE:
+ usage();
+ exit(1);
+ default:
+ break;
+ }
+
+ SOCK_STARTUP;
+
+ session.callback = snmp_input;
+ session.callback_magic = NULL;
+
+ /*
+ * setup the local engineID which may be for either or both of the
+ * contextEngineID and/or the securityEngineID.
+ */
+ setup_engineID(NULL, NULL);
+
+ /* if we don't have a contextEngineID set via command line
+ arguments, use our internal engineID as the context. */
+ if (session.contextEngineIDLen == 0 ||
+ session.contextEngineID == NULL) {
+ session.contextEngineID =
+ snmpv3_generate_engineID(&session.contextEngineIDLen);
+ }
+
+ if (session.version == SNMP_VERSION_3 && !inform) {
+ /*
+ * for traps, we use ourselves as the authoritative engine
+ * which is really stupid since command line apps don't have a
+ * notion of a persistent engine. Hence, our boots and time
+ * values are probably always really wacked with respect to what
+ * a manager would like to see.
+ *
+ * The following should be enough to:
+ *
+ * 1) prevent the library from doing discovery for engineid & time.
+ * 2) use our engineid instead of the remote engineid for
+ * authoritative & privacy related operations.
+ * 3) The remote engine must be configured with users for our engineID.
+ *
+ * -- Wes
+ */
+
+ /*
+ * pick our own engineID
+ */
+ if (session.securityEngineIDLen == 0 ||
+ session.securityEngineID == NULL) {
+ session.securityEngineID =
+ snmpv3_generate_engineID(&session.securityEngineIDLen);
+ }
+
+ /*
+ * set boots and time, which will cause problems if this
+ * machine ever reboots and a remote trap receiver has cached our
+ * boots and time... I'll cause a not-in-time-window report to
+ * be sent back to this machine.
+ */
+ if (session.engineBoots == 0)
+ session.engineBoots = 1;
+ if (session.engineTime == 0) /* not really correct, */
+ session.engineTime = get_uptime(); /* but it'll work. Sort of. */
+ }
+
+ ss = snmp_add(&session,
+ netsnmp_transport_open_client("snmptrap", session.peername),
+ NULL, NULL);
+ if (ss == NULL) {
+ /*
+ * diagnose netsnmp_transport_open_client and snmp_add errors with
+ * the input netsnmp_session pointer
+ */
+ snmp_sess_perror("snmptrap", &session);
+ SOCK_CLEANUP;
+ exit(1);
+ }
+
+#ifndef NETSNMP_DISABLE_SNMPV1
+ if (session.version == SNMP_VERSION_1) {
+ if (inform) {
+ fprintf(stderr, "Cannot send INFORM as SNMPv1 PDU\n");
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ pdu = snmp_pdu_create(SNMP_MSG_TRAP);
+ if ( !pdu ) {
+ fprintf(stderr, "Failed to create trap PDU\n");
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ pdu_in_addr_t = (in_addr_t *) pdu->agent_addr;
+ if (arg == argc) {
+ fprintf(stderr, "No enterprise oid\n");
+ usage();
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ if (argv[arg][0] == 0) {
+ pdu->enterprise = (oid *) malloc(sizeof(objid_enterprise));
+ memcpy(pdu->enterprise, objid_enterprise,
+ sizeof(objid_enterprise));
+ pdu->enterprise_length =
+ sizeof(objid_enterprise) / sizeof(oid);
+ } else {
+ name_length = MAX_OID_LEN;
+ if (!snmp_parse_oid(argv[arg], name, &name_length)) {
+ snmp_perror(argv[arg]);
+ usage();
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ pdu->enterprise = (oid *) malloc(name_length * sizeof(oid));
+ memcpy(pdu->enterprise, name, name_length * sizeof(oid));
+ pdu->enterprise_length = name_length;
+ }
+ if (++arg >= argc) {
+ fprintf(stderr, "Missing agent parameter\n");
+ usage();
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ agent = argv[arg];
+ if (agent != NULL && strlen(agent) != 0) {
+ int ret = netsnmp_gethostbyname_v4(agent, pdu_in_addr_t);
+ if (ret < 0) {
+ fprintf(stderr, "unknown host: %s\n", agent);
+ exit(1);
+ }
+ } else {
+ *pdu_in_addr_t = get_myaddr();
+ }
+ if (++arg == argc) {
+ fprintf(stderr, "Missing generic-trap parameter\n");
+ usage();
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ trap = argv[arg];
+ pdu->trap_type = atoi(trap);
+ if (++arg == argc) {
+ fprintf(stderr, "Missing specific-trap parameter\n");
+ usage();
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ specific = argv[arg];
+ pdu->specific_type = atoi(specific);
+ if (++arg == argc) {
+ fprintf(stderr, "Missing uptime parameter\n");
+ usage();
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ description = argv[arg];
+ if (description == NULL || *description == 0)
+ pdu->time = get_uptime();
+ else
+ pdu->time = atol(description);
+ } else
+#endif
+ {
+ long sysuptime;
+ char csysuptime[20];
+
+ pdu = snmp_pdu_create(inform ? SNMP_MSG_INFORM : SNMP_MSG_TRAP2);
+ if ( !pdu ) {
+ fprintf(stderr, "Failed to create notification PDU\n");
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ if (arg == argc) {
+ fprintf(stderr, "Missing up-time parameter\n");
+ usage();
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ trap = argv[arg];
+ if (*trap == 0) {
+ sysuptime = get_uptime();
+ sprintf(csysuptime, "%ld", sysuptime);
+ trap = csysuptime;
+ }
+ snmp_add_var(pdu, objid_sysuptime,
+ sizeof(objid_sysuptime) / sizeof(oid), 't', trap);
+ if (++arg == argc) {
+ fprintf(stderr, "Missing trap-oid parameter\n");
+ usage();
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ if (snmp_add_var
+ (pdu, objid_snmptrap, sizeof(objid_snmptrap) / sizeof(oid),
+ 'o', argv[arg]) != 0) {
+ snmp_perror(argv[arg]);
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ }
+ arg++;
+
+ while (arg < argc) {
+ arg += 3;
+ if (arg > argc) {
+ fprintf(stderr, "%s: Missing type/value for variable\n",
+ argv[arg - 3]);
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ name_length = MAX_OID_LEN;
+ if (!snmp_parse_oid(argv[arg - 3], name, &name_length)) {
+ snmp_perror(argv[arg - 3]);
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ if (snmp_add_var
+ (pdu, name, name_length, argv[arg - 2][0],
+ argv[arg - 1]) != 0) {
+ snmp_perror(argv[arg - 3]);
+ SOCK_CLEANUP;
+ exit(1);
+ }
+ }
+
+ if (inform)
+ status = snmp_synch_response(ss, pdu, &response);
+ else
+ status = snmp_send(ss, pdu) == 0;
+ if (status) {
+ snmp_sess_perror(inform ? "snmpinform" : "snmptrap", ss);
+ if (!inform)
+ snmp_free_pdu(pdu);
+ exitval = 1;
+ } else if (inform)
+ snmp_free_pdu(response);
+
+ snmp_close(ss);
+ snmp_shutdown("snmpapp");
+ SOCK_CLEANUP;
+ return exitval;
+}