summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/snmpd/control.c12
-rw-r--r--usr.sbin/snmpd/snmp.h52
-rw-r--r--usr.sbin/snmpd/snmpd.h3
-rw-r--r--usr.sbin/snmpd/snmpe.c154
4 files changed, 217 insertions, 4 deletions
diff --git a/usr.sbin/snmpd/control.c b/usr.sbin/snmpd/control.c
index 24023e798c5..a048f652fa5 100644
--- a/usr.sbin/snmpd/control.c
+++ b/usr.sbin/snmpd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.1 2007/12/05 09:22:44 reyk Exp $ */
+/* $OpenBSD: control.c,v 1.2 2008/01/16 09:36:30 reyk Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -230,6 +230,16 @@ control_dispatch_imsg(int fd, short event, void *arg)
}
c->flags |= CTL_CONN_NOTIFY;
break;
+ case IMSG_SNMP_TRAP:
+ if (snmpe_trap(&c->ibuf, imsg.hdr.pid) == -1) {
+ log_debug("control_dispatch_imsg: "
+ "received invalid trap (pid %d)",
+ imsg.hdr.pid);
+ imsg_free(&imsg);
+ control_close(fd);
+ return;
+ }
+ break;
default:
log_debug("control_dispatch_imsg: "
"error handling imsg %d", imsg.hdr.type);
diff --git a/usr.sbin/snmpd/snmp.h b/usr.sbin/snmpd/snmp.h
index 0ba2d24d287..7d67cb44252 100644
--- a/usr.sbin/snmpd/snmp.h
+++ b/usr.sbin/snmpd/snmp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmp.h,v 1.2 2008/01/11 12:12:14 reyk Exp $ */
+/* $OpenBSD: snmp.h,v 1.3 2008/01/16 09:36:30 reyk Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
@@ -19,6 +19,54 @@
#ifndef SNMP_HEADER
#define SNMP_HEADER
+/*
+ * SNMP IMSG interface
+ */
+
+#define SNMP_MAX_OID_LEN 128 /* max size of the OID _string_ */
+#define SNMP_SOCKET "/var/run/snmpd.sock"
+
+enum snmp_type {
+ SNMP_IPADDR = 0,
+ SNMP_COUNTER32 = 1,
+ SNMP_GAUGE32 = 2,
+ SNMP_UNSIGNED32 = 2,
+ SNMP_TIMETICKS = 3,
+ SNMP_OPAQUE = 4,
+ SNMP_NSAPADDR = 5,
+ SNMP_COUNTER64 = 6,
+ SNMP_UINTEGER32 = 7,
+
+ SNMP_INTEGER32 = 100,
+ SNMP_BITSTRING = 101,
+ SNMP_OCTETSTRING = 102,
+ SNMP_NULL = 103,
+ SNMP_OBJECT = 104
+};
+
+enum snmp_imsg_ctl {
+ IMSG_SNMP_TRAP = 1000, /* something that works everywhere */
+ IMSG_SNMP_ELEMENT,
+ IMSG_SNMP_END
+};
+
+struct snmp_imsg_hdr {
+ u_int16_t imsg_type;
+ u_int16_t imsg_len;
+ u_int32_t imsg_peerid;
+ pid_t imsg_pid;
+};
+
+struct snmp_imsg {
+ char snmp_oid[SNMP_MAX_OID_LEN];
+ u_int8_t snmp_type;
+ u_int16_t snmp_len;
+};
+
+/*
+ * SNMP BER types
+ */
+
enum snmp_version {
SNMP_V1 = 0,
SNMP_V2 = 1,
@@ -46,7 +94,9 @@ enum snmp_application {
SNMP_T_UNSIGNED32 = 2,
SNMP_T_TIMETICKS = 3,
SNMP_T_OPAQUE = 4,
+ SNMP_T_NSAPADDR = 5,
SNMP_T_COUNTER64 = 6,
+ SNMP_T_UINTEGER32 = 7
};
enum snmp_generic_trap {
diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h
index fc6418536b1..7499ea4231e 100644
--- a/usr.sbin/snmpd/snmpd.h
+++ b/usr.sbin/snmpd/snmpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmpd.h,v 1.10 2008/01/03 15:03:47 reyk Exp $ */
+/* $OpenBSD: snmpd.h,v 1.11 2008/01/16 09:36:30 reyk Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
@@ -387,6 +387,7 @@ struct kif_addr *kr_getnextaddr(struct in_addr *);
/* snmpe.c */
pid_t snmpe(struct snmpd *, int [2]);
+int snmpe_trap(struct imsgbuf *, pid_t);
/* mps.c */
struct ber_element *
diff --git a/usr.sbin/snmpd/snmpe.c b/usr.sbin/snmpd/snmpe.c
index 4db07333c10..44960a0abf7 100644
--- a/usr.sbin/snmpd/snmpe.c
+++ b/usr.sbin/snmpd/snmpe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: snmpe.c,v 1.10 2008/01/12 13:57:43 reyk Exp $ */
+/* $OpenBSD: snmpe.c,v 1.11 2008/01/16 09:36:30 reyk Exp $ */
/*
* Copyright (c) 2007 Reyk Floeter <reyk@vantronix.net>
@@ -804,3 +804,155 @@ snmpe_recvmsg(int fd, short sig, void *arg)
if (resp != NULL)
ber_free_elements(resp);
}
+
+int
+snmpe_trap(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);
+}