summaryrefslogtreecommitdiff
path: root/usr.sbin/snmpd/trap.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/snmpd/trap.c')
-rw-r--r--usr.sbin/snmpd/trap.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/usr.sbin/snmpd/trap.c b/usr.sbin/snmpd/trap.c
new file mode 100644
index 00000000000..569d82010ce
--- /dev/null
+++ b/usr.sbin/snmpd/trap.c
@@ -0,0 +1,192 @@
+/* $OpenBSD: trap.c,v 1.1 2008/01/16 09:42:29 reyk Exp $ */
+
+/*
+ * Copyright (c) 2008 Reyk Floeter <reyk@vantronix.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, 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 <sys/queue.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/tree.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <event.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include "snmpd.h"
+
+int
+trap_request(struct imsgbuf *ibuf, pid_t pid)
+{
+ struct imsg imsg;
+ int ret = -1, n, x = 0;
+ int done = 0;
+ struct snmp_imsg *sm;
+ u_int32_t d;
+ u_int64_t l;
+ u_int8_t *c;
+ char o[SNMP_MAX_OID_LEN];
+ struct ber_element *ber, *trap = NULL, *oid = NULL, *a;
+ size_t len;
+
+ ber = trap = ber_add_sequence(NULL);
+
+ while (!done) {
+ while (!done) {
+ if ((n = imsg_get(ibuf, &imsg)) == -1)
+ goto done;
+ if (n == 0)
+ break;
+ switch (imsg.hdr.type) {
+ case IMSG_SNMP_ELEMENT:
+ if (imsg.hdr.len < (IMSG_HEADER_SIZE +
+ sizeof(struct snmp_imsg)))
+ goto imsgdone;
+
+ sm = (struct snmp_imsg *)imsg.data;
+
+ if (oid == NULL) {
+ /* First element must be the trap OID */
+ if (sm->snmp_type != SNMP_NULL)
+ goto imsgdone;
+ ber = oid = ber_printf_elements(ber,
+ "{o0}", sm->snmp_oid);
+ break;
+ }
+
+ ber = a = ber_add_sequence(ber);
+ a = ber_add_oidstring(a, sm->snmp_oid);
+
+ switch (sm->snmp_type) {
+ case SNMP_OBJECT:
+ if (sm->snmp_len != sizeof(o))
+ goto imsgdone;
+ bcopy(sm + 1, &o, sm->snmp_len);
+ a = ber_add_oidstring(a, o);
+ break;
+ case SNMP_BITSTRING:
+ case SNMP_OCTETSTRING:
+ if ((sm->snmp_len < 1) ||
+ (sm->snmp_len >= SNMPD_MAXSTRLEN))
+ goto imsgdone;
+ if ((c =
+ calloc(1, sm->snmp_len)) == NULL)
+ goto imsgdone;
+ bcopy(sm + 1, c, sm->snmp_len);
+ if (sm->snmp_type == SNMP_BITSTRING)
+ a = ber_add_bitstring(a, c,
+ sm->snmp_len);
+ else
+ a = ber_add_nstring(a, c,
+ sm->snmp_len);
+ a->be_free = 1;
+ break;
+ case SNMP_NULL:
+ a = ber_add_null(a);
+ break;
+ case SNMP_INTEGER32:
+ case SNMP_IPADDR:
+ case SNMP_COUNTER32:
+ case SNMP_GAUGE32:
+ case SNMP_TIMETICKS:
+ case SNMP_OPAQUE:
+ case SNMP_UINTEGER32:
+ if (sm->snmp_len != sizeof(d))
+ goto imsgdone;
+ bcopy(sm + 1, &d, sm->snmp_len);
+ a = ber_add_integer(a, d);
+ break;
+ case SNMP_COUNTER64:
+ if (sm->snmp_len != sizeof(l))
+ goto imsgdone;
+ bcopy(sm + 1, &l, sm->snmp_len);
+ a = ber_add_integer(a, d);
+ break;
+ default:
+ log_debug("snmpe_trap: illegal type %d",
+ sm->snmp_type);
+ imsg_free(&imsg);
+ goto imsgdone;
+ }
+ switch (sm->snmp_type) {
+ case SNMP_INTEGER32:
+ case SNMP_BITSTRING:
+ case SNMP_OCTETSTRING:
+ case SNMP_NULL:
+ case SNMP_OBJECT:
+ /* universal types */
+ break;
+ case SNMP_IPADDR:
+ case SNMP_COUNTER32:
+ case SNMP_GAUGE32:
+ case SNMP_TIMETICKS:
+ case SNMP_OPAQUE:
+ case SNMP_NSAPADDR:
+ case SNMP_COUNTER64:
+ case SNMP_UINTEGER32:
+ /* application-specific types */
+ ber_set_header(a, BER_CLASS_APPLICATION,
+ sm->snmp_type);
+ break;
+ }
+ x++;
+ break;
+ case IMSG_SNMP_END:
+ done = 1;
+ break;
+ default:
+ log_debug("snmpe_trap: illegal imsg %d",
+ imsg.hdr.type);
+ goto imsgdone;
+ }
+ imsg_free(&imsg);
+ }
+ if (done)
+ break;
+ if ((n = imsg_read(ibuf)) == -1)
+ goto done;
+ if (n == 0)
+ goto done;
+ }
+
+ len = ber_calc_len(trap);
+ log_debug("snmpe_trap: %d bytes from pid %d", len, pid);
+
+ /* XXX send trap to registered receivers */
+
+#ifdef DEBUG
+ snmpe_debug_elements(trap);
+#endif
+
+ ret = 0;
+ imsgdone:
+ if (ret != 0)
+ imsg_free(&imsg);
+ done:
+ ber_free_elements(trap);
+ return (ret);
+}